正如我在this article中解釋的那樣,使用Hibernate持久化JSON對象非常容易。
您不必手動創建所有這些類型的,你可以通過Maven的中央使用以下依賴簡單地得到 他們:
<dependency>
<groupId>com.vladmihalcea</groupId>
<artifactId>hibernate-types-52</artifactId>
<version>${hibernate-types.version}</version>
</dependency>
欲瞭解更多信息,請查看hibernate-types open-source project。
現在來解釋它是如何工作的。
我寫了an article關於如何在PostgreSQL和MySQL上映射JSON對象。
對於PostgreSQL,你需要發送的JSON對象以二進制形式:
public class JsonBinaryType
extends AbstractSingleColumnStandardBasicType<Object>
implements DynamicParameterizedType {
public JsonBinaryType() {
super(
JsonBinarySqlTypeDescriptor.INSTANCE,
new JsonTypeDescriptor()
);
}
public String getName() {
return "jsonb";
}
@Override
public void setParameterValues(Properties parameters) {
((JsonTypeDescriptor) getJavaTypeDescriptor())
.setParameterValues(parameters);
}
}
的JsonBinarySqlTypeDescriptor
看起來是這樣的:
public class JsonBinarySqlTypeDescriptor
extends AbstractJsonSqlTypeDescriptor {
public static final JsonBinarySqlTypeDescriptor INSTANCE =
new JsonBinarySqlTypeDescriptor();
@Override
public <X> ValueBinder<X> getBinder(
final JavaTypeDescriptor<X> javaTypeDescriptor) {
return new BasicBinder<X>(javaTypeDescriptor, this) {
@Override
protected void doBind(
PreparedStatement st,
X value,
int index,
WrapperOptions options) throws SQLException {
st.setObject(index,
javaTypeDescriptor.unwrap(
value, JsonNode.class, options), getSqlType()
);
}
@Override
protected void doBind(
CallableStatement st,
X value,
String name,
WrapperOptions options)
throws SQLException {
st.setObject(name,
javaTypeDescriptor.unwrap(
value, JsonNode.class, options), getSqlType()
);
}
};
}
}
和JsonTypeDescriptor
這樣的:
public class JsonTypeDescriptor
extends AbstractTypeDescriptor<Object>
implements DynamicParameterizedType {
private Class<?> jsonObjectClass;
@Override
public void setParameterValues(Properties parameters) {
jsonObjectClass = ((ParameterType) parameters.get(PARAMETER_TYPE))
.getReturnedClass();
}
public JsonTypeDescriptor() {
super(Object.class, new MutableMutabilityPlan<Object>() {
@Override
protected Object deepCopyNotNull(Object value) {
return JacksonUtil.clone(value);
}
});
}
@Override
public boolean areEqual(Object one, Object another) {
if (one == another) {
return true;
}
if (one == null || another == null) {
return false;
}
return JacksonUtil.toJsonNode(JacksonUtil.toString(one)).equals(
JacksonUtil.toJsonNode(JacksonUtil.toString(another)));
}
@Override
public String toString(Object value) {
return JacksonUtil.toString(value);
}
@Override
public Object fromString(String string) {
return JacksonUtil.fromString(string, jsonObjectClass);
}
@SuppressWarnings({ "unchecked" })
@Override
public <X> X unwrap(Object value, Class<X> type, WrapperOptions options) {
if (value == null) {
return null;
}
if (String.class.isAssignableFrom(type)) {
return (X) toString(value);
}
if (Object.class.isAssignableFrom(type)) {
return (X) JacksonUtil.toJsonNode(toString(value));
}
throw unknownUnwrap(type);
}
@Override
public <X> Object wrap(X value, WrapperOptions options) {
if (value == null) {
return null;
}
return fromString(value.toString());
}
}
現在,您需要在任何一個類上聲明新類型在package-info.java包級descriptior VEL或:
@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
與實體映射將是這樣的:
@Type(type = "jsonb")
@Column(columnDefinition = "json")
private Location location;
如果您在使用Hibernate 5或更高版本,然後JSON
類型是registered automatically by Postgre92Dialect。
否則,你需要自己註冊它:
public class PostgreSQLDialect extends PostgreSQL91Dialect {
public PostgreSQL92Dialect() {
super();
this.registerColumnType(Types.JAVA_OBJECT, "json");
}
}
我知道這是一個有點舊的,但看看我的答案http://stackoverflow.com/a/26126168/1535995類似的問題 – Sasa7812