对于一些不经常更新的静态数据,我们喜欢使用json格式存储。推荐的做法是将json数据存储在key-value数据库,但这无疑增加了技术成本,所以我们通常还是存储在RDB数据库中。我们在使用hibernate,对json数据的存取期望是,存能自动转换为json格式存储,取能自动将json数据转换为对象数据。在数据库方面,Mysql5.7版本以后新增的功能,Mysql提供了一个原生的Json类型,Json值将不再以字符串的形式存储,而是采用一种允许快速读取文本元素(document elements)的内部二进制(internal binary)格式。在Json列插入或者更新的时候将会自动验证Json文本,未通过验证的文本将产生一个错误信息。而除了mysql,pg极少部分支持json字段类型的其他数据库,还是需要大文本字段进行存储。
关键技术: hibernate-types 将Java对象或Jackson JsonNode为JPA实体属性。
com.vladmihalcea
hibernate-types-52
2.10.1
import com.alibaba.fastjson.JSONObject;
import com.vladmihalcea.hibernate.type.array.IntArrayType;
import com.vladmihalcea.hibernate.type.array.StringArrayType;
import com.vladmihalcea.hibernate.type.json.JsonBinaryType;
import com.vladmihalcea.hibernate.type.json.JsonStringType;
import lombok.Data;
import org.hibernate.annotations.Type;
import org.hibernate.annotations.TypeDef;
import org.hibernate.annotations.TypeDefs;
import javax.persistence.*;
@Data
@Entity
@Table(name = "parents")
@TypeDefs({
@TypeDef(name = "string-array", typeClass = StringArrayType.class),
@TypeDef(name = "json", typeClass = JsonStringType.class),
@TypeDef(name = "jsonb", typeClass = JsonBinaryType.class)
})
public class TestEntity implements Serializable {
@Id
private Long id;
@Column(name = "attr")
@Type(type = "jsonb")
private JSONObject attr;
@Column(name = "user_list")
@Type(type = "json")
private List userList;
@Column(name = "ava_img")
@Type(type = "string-array")
private String[] avaImg;
}
以上为常规操作,在多数据库使用时,你会发现,JsonStringType 类型会转为数据库默认的 varchar(255),根本就存储不了长一点的json数据。
也许网络上一搜JsonStringType适配性问题,答案基本都是建议用 @Column(columnDefinition = "json") 、 @Column(columnDefinition = "varchar(max)") 这种写法,我在上一篇文章中说了,columnDefinition具有不可移植性,只能适配一种或一类数据库。所以,需要自定义扩展JsonStringType。
12对应数据库字段类型是varchar,这也太坑了,直接给JsonStringType对应的数据库字段类型写死。
import com.fasterxml.jackson.databind.ObjectMapper;
import com.vladmihalcea.hibernate.type.AbstractHibernateType;
import com.vladmihalcea.hibernate.type.json.internal.JsonTypeDescriptor;
import com.vladmihalcea.hibernate.type.util.Configuration;
import com.vladmihalcea.hibernate.type.util.ObjectMapperWrapper;
import org.hibernate.usertype.DynamicParameterizedType;
import java.lang.reflect.Type;
import java.util.Properties;
public class MyJsonStringType extends AbstractHibernateType
import com.vladmihalcea.hibernate.type.json.internal.AbstractJsonSqlTypeDescriptor;
import org.hibernate.type.descriptor.ValueBinder;
import org.hibernate.type.descriptor.WrapperOptions;
import org.hibernate.type.descriptor.java.JavaTypeDescriptor;
import org.hibernate.type.descriptor.sql.BasicBinder;
import java.sql.CallableStatement;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
public class MyJsonStringSqlTypeDescriptor extends AbstractJsonSqlTypeDescriptor {
public static final MyJsonStringSqlTypeDescriptor INSTANCE = new MyJsonStringSqlTypeDescriptor();
public MyJsonStringSqlTypeDescriptor() {
}
public ValueBinder getBinder(final JavaTypeDescriptor javaTypeDescriptor) {
return new BasicBinder(javaTypeDescriptor, this) {
protected void doBind(PreparedStatement st, X value, int index, WrapperOptions options) throws SQLException {
st.setString(index, (String)javaTypeDescriptor.unwrap(value, String.class, options));
}
protected void doBind(CallableStatement st, X value, String name, WrapperOptions options) throws SQLException {
st.setString(name, (String)javaTypeDescriptor.unwrap(value, String.class, options));
}
};
}
protected Object extractJson(ResultSet rs, String name) throws SQLException {
return rs.getString(name);
}
protected Object extractJson(CallableStatement statement, int index) throws SQLException {
return statement.getString(index);
}
protected Object extractJson(CallableStatement statement, String name) throws SQLException {
return statement.getString(name);
}
}
实体json定义改为
@TypeDef(name="json",typeClass = MyJsonStringType.class)
大功告成,下边就可以根据不同数据库自适应数据库json字段类型
mysql适配json字段
public class MySQLDialect extends MySQL5InnoDBDialect {
public MySQLDialect() {
registerColumnType(Types.OTHER, "json");
}
}
配置文件:
spring.jpa.database-platform: xxxx.xxxx.xx.MySQLDialect
达梦数据库适配json字段
public class DaMengDialect extends DmDialect {
public DaMengDialect() {
registerColumnType(Types.OTHER, "LONGVARCHAR");
}
}
配置文件:
spring.jpa.database-platform: xxxx.xxxx.xx.DaMengDialect
原文地址:https://www.cnblogs.com/luze/p/17185828.html
参与评论