1 package com.vladmihalcea.hibernate.type.json;
2
3 import com.fasterxml.jackson.databind.ObjectMapper;
4 import com.vladmihalcea.hibernate.type.AbstractHibernateType;
5 import com.vladmihalcea.hibernate.type.json.internal.JsonSqlTypeDescriptor;
6 import com.vladmihalcea.hibernate.type.json.internal.JsonTypeDescriptor;
7 import com.vladmihalcea.hibernate.type.util.Configuration;
8 import com.vladmihalcea.hibernate.type.util.ObjectMapperWrapper;
9 import org.hibernate.type.descriptor.sql.SqlTypeDescriptor;
10 import org.hibernate.usertype.DynamicParameterizedType;
11 import org.hibernate.usertype.ParameterizedType;
12
13 import javax.persistence.Column;
14 import java.lang.reflect.Type;
15 import java.util.Properties;
16
17 /**
18 * <p>
19 * {@link JsonType} allows you to map any given JSON object (e.g., POJO, <code>Map<String, Object></code>, List<T>, <code>JsonNode</code>) on any of the following database systems:
20 * </p>
21 * <ul>
22 * <li><strong>PostgreSQL</strong> - for both <strong><code>jsonb</code></strong> and <strong><code>json</code></strong> column types</li>
23 * <li><strong>MySQL</strong> - for the <strong><code>json</code></strong> column type</li>
24 * <li><strong>SQL Server</strong> - for the <strong><code>NVARCHAR</code></strong> column type storing JSON</li>
25 * <li><strong>Oracle</strong> - for the <strong><code>JSON</code></strong> column type if you're using Oracle 21c or the <strong><code>VARCHAR</code></strong> column type storing JSON if you're using an older Oracle version</li>
26 * <li><strong>H2</strong> - for the <strong><code>json</code></strong> column type</li>
27 * </ul>
28 * <p>
29 * If you switch to Oracle 21c from an older version, then you should also migrate your {@code JSON} columns to the native JSON type since this binary type performs better than
30 * {@code VARCHAR2} or {@code BLOB} column types.
31 * </p>
32 * <p>
33 * However, if you don't want to migrate to the new {@code JSON} data type,
34 * then you just have to provide the column type via the JPA {@link Column#columnDefinition()} attribute,
35 * like in the following example:
36 * </p>
37 * <pre>
38 * {@code @Type(}type = "com.vladmihalcea.hibernate.type.json.JsonType")
39 * {@code @Column(}columnDefinition = "VARCHAR2")
40 * </pre>
41 * <p>
42 * For more details about how to use the {@link JsonType}, check out <a href="https://vladmihalcea.com/how-to-map-json-objects-using-generic-hibernate-types/">this article</a> on <a href="https://vladmihalcea.com/">vladmihalcea.com</a>.
43 * </p>
44 * <p>
45 * If you are using <strong>Oracle</strong> and want to store JSON objects in a <code>BLOB</code> column type, then you can use the {@link JsonBlobType} instead. For more details, check out <a href="https://vladmihalcea.com/oracle-json-jpa-hibernate/">this article</a> on <a href="https://vladmihalcea.com/">vladmihalcea.com</a>.
46 * </p>
47 * <p>
48 * Or, you can use the {@link JsonType}, but you'll have to specify the underlying column type
49 * using the JPA {@link Column#columnDefinition()} attribute, like this:
50 * </p>
51 * <pre>
52 * {@code @Type(}type = "com.vladmihalcea.hibernate.type.json.JsonType")
53 * {@code @Column(}columnDefinition = "BLOB")
54 * </pre>
55 * @author Vlad Mihalcea
56 */
57 public class JsonType
58 extends AbstractHibernateType<Object> implements DynamicParameterizedType {
59
60 public static final JsonType INSTANCE = new JsonType();
61
62 public JsonType() {
63 super(
64 new JsonSqlTypeDescriptor(),
65 new JsonTypeDescriptor(Configuration.INSTANCE.getObjectMapperWrapper())
66 );
67 }
68
69 public JsonType(Type javaType) {
70 super(
71 new JsonSqlTypeDescriptor(),
72 new JsonTypeDescriptor(Configuration.INSTANCE.getObjectMapperWrapper(), javaType)
73 );
74 }
75
76 public JsonType(Configuration configuration) {
77 super(
78 new JsonSqlTypeDescriptor(configuration.getProperties()),
79 new JsonTypeDescriptor(configuration.getObjectMapperWrapper()),
80 configuration
81 );
82 }
83
84 public JsonType(ObjectMapper objectMapper) {
85 super(
86 new JsonSqlTypeDescriptor(),
87 new JsonTypeDescriptor(new ObjectMapperWrapper(objectMapper))
88 );
89 }
90
91 public JsonType(ObjectMapperWrapper objectMapperWrapper) {
92 super(
93 new JsonSqlTypeDescriptor(),
94 new JsonTypeDescriptor(objectMapperWrapper)
95 );
96 }
97
98 public JsonType(ObjectMapper objectMapper, Type javaType) {
99 super(
100 new JsonSqlTypeDescriptor(),
101 new JsonTypeDescriptor(new ObjectMapperWrapper(objectMapper), javaType)
102 );
103 }
104
105 public JsonType(ObjectMapperWrapper objectMapperWrapper, Type javaType) {
106 super(
107 new JsonSqlTypeDescriptor(),
108 new JsonTypeDescriptor(objectMapperWrapper, javaType)
109 );
110 }
111
112 public String getName() {
113 return "json";
114 }
115
116 @Override
117 public void setParameterValues(Properties parameters) {
118 ((JsonTypeDescriptor) getJavaTypeDescriptor()).setParameterValues(parameters);
119 SqlTypeDescriptor sqlTypeDescriptor = getSqlTypeDescriptor();
120 if (sqlTypeDescriptor instanceof ParameterizedType) {
121 ParameterizedType parameterizedType = (ParameterizedType) sqlTypeDescriptor;
122 parameterizedType.setParameterValues(parameters);
123 }
124 }
125 }