You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.26 10:26:35