如何为PostgreSQL的JSON/JSON(B)实现Hibernate自定义类型
实现字符串类型的原始JSON Hibernate类型(基于Hibernate-Types)
嘿,我来帮你把这个Raw JSON字符串类型的Hibernate实现补全并优化一下!你已经选对了方向——继承Hibernate-Types的ImmutableType来简化不可变类型的开发,下面是完整的可运行实现,还有对应的使用说明:
1. 完整的RawJsonStringType实现
这个类型会把Java字符串映射到数据库的JSON类型,直接复用Hibernate的类型描述器来减少重复代码:
import com.vladmihalcea.hibernate.type.ImmutableType; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.type.descriptor.java.StringJavaType; import org.hibernate.type.descriptor.jdbc.JsonJdbcType; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class RawJsonStringType extends ImmutableType<String> { // 构造方法:指定Java类型、Java类型描述器、JDBC类型描述器 public RawJsonStringType() { super(String.class, StringJavaType.INSTANCE, JsonJdbcType.INSTANCE); } // 从结果集读取JSON字符串 @Override protected String get(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner) throws SQLException { return rs.getString(names[0]); } // 将JSON字符串写入PreparedStatement @Override protected void set(PreparedStatement st, String value, int index, SharedSessionContractImplementor session) throws SQLException { if (value == null) { st.setNull(index, JsonJdbcType.INSTANCE.getJdbcTypeCode()); } else { st.setString(index, value); } } // 给类型定义别名,方便在实体注解中使用 @Override public String getName() { return "rawjson"; } }
2. 支持JSONB的版本(比如PostgreSQL)
如果你的数据库用的是JSONB类型(比如PostgreSQL),可以单独实现一个RawJsonbStringType,只需要替换JDBC类型描述器:
import com.vladmihalcea.hibernate.type.ImmutableType; import org.hibernate.engine.spi.SharedSessionContractImplementor; import org.hibernate.type.descriptor.java.StringJavaType; import org.hibernate.type.descriptor.jdbc.JsonbJdbcType; import java.sql.PreparedStatement; import java.sql.ResultSet; import java.sql.SQLException; public class RawJsonbStringType extends ImmutableType<String> { public RawJsonbStringType() { super(String.class, StringJavaType.INSTANCE, JsonbJdbcType.INSTANCE); } @Override protected String get(ResultSet rs, String[] names, SharedSessionContractImplementor session, Object owner) throws SQLException { return rs.getString(names[0]); } @Override protected void set(PreparedStatement st, String value, int index, SharedSessionContractImplementor session) throws SQLException { if (value == null) { st.setNull(index, JsonbJdbcType.INSTANCE.getJdbcTypeCode()); } else { st.setString(index, value); } } @Override public String getName() { return "rawjsonb"; } }
3. 实体中的使用示例
现在你可以在实体类里直接用自定义的类型别名了:
import jakarta.persistence.Entity; import jakarta.persistence.Id; import org.hibernate.annotations.Type; @Entity public class MyEntity { @Id private Long id; // 映射到数据库JSON类型 @Type(type = "rawjson") private String jsonContent; // 如果用JSONB的话,替换成这个注解 // @Type(type = "rawjsonb") // private String jsonbContent; // 构造器、getter、setter方法请自行补充 }
4. 注意事项
- 确保你的项目已经引入了对应版本的Hibernate-Types依赖:比如Hibernate 6.x用
hibernate-types-60,Hibernate 5.x用hibernate-types-55。 - 这个实现兼容主流数据库(PostgreSQL、MySQL、SQL Server等),不同数据库的JSON/JDBC类型处理已经由Hibernate的
JsonJdbcType/JsonbJdbcType自动适配。 - 因为继承了
ImmutableType,这个类型会把JSON字符串当作不可变对象处理——如果需要支持可变的JSON操作,你可以换成继承MutableType,不过对于字符串类型的JSON来说,不可变已经足够使用。
内容的提问来源于stack exchange,提问作者Rad
相关产品推荐
相关产品推荐

