正如我在本文中解释的那样,使用Hibernate持久化JSON对象非常容易.
您不必手动创建所有这些类型,只需使用以下依赖项通过Maven Central获取它们:
Run Code Online (Sandbox Code Playgroud)<dependency> <groupId>com.vladmihalcea</groupId> <artifactId>hibernate-types-52</artifactId> <version>${hibernate-types.version}</version> </dependency>
有关更多信息,请查看hibernate类型的开源项目.
我写了一篇关于如何在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);
}
}
Run Code Online (Sandbox Code Playgroud)
该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()
);
}
};
}
}
Run Code Online (Sandbox Code Playgroud)
之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());
}
}
Run Code Online (Sandbox Code Playgroud)
现在,您需要在类级别或package-info.java包级别描述符中声明新类型:
@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
Run Code Online (Sandbox Code Playgroud)
实体映射将如下所示:
@Type(type = "jsonb")
@Column(columnDefinition = "json")
private Location location;
Run Code Online (Sandbox Code Playgroud)
而已!
我们使用这种方法来简化设计并摆脱许多 dto(我们滥用它们太多了)。基本上,它对我们有用。
然而,在我们的 REST 模型中,我们试图不公开对象的其他关系,因为您始终可以创建另一个 REST 资源来访问它们。
所以我们只需@JsonIgnore
对关系映射添加注释,例如@OneToMany
or@ManyToOne
使它们短暂。
我发现的另一个问题是,如果您仍然想返回这些关系,则必须对Join.FETCH
它们使用策略或将事务管理移至更高级别,以便当响应序列化为 JSON(在视图模式中打开会话)时事务仍然存在。我认为这两种解决方案都不是很好。
归档时间: |
|
查看次数: |
16096 次 |
最近记录: |