【问题标题】:Creating custom user types for jsonb columns in hibernate postgresql在休眠 postgresql 中为 jsonb 列创建自定义用户类型
【发布时间】:2018-01-26 02:54:01
【问题描述】:

我正在尝试将我的 spring mvc 项目数据库从 mongodb 迁移到 postgresql。 春季版 4.3.8.RELEASE 休眠版本 5.2.10.Final Postgresql 数据库版本是 9.6

我正在尝试为以下实体实现创建、读取、更新操作。

BeneficiaryData.java

@Document(collection = "beneficiary_data")
public class BeneficiaryData extends BaseEntity {

    @Id
    private String id;
    private Integer beneficiaryId;

    private Map<Integer, Object> customData;
    private Map<Integer, List<Integer>> customMultipleData;
    private Date lastUpdatedOn;

    public BeneficiaryData() {
    }
}

在 mongodb 中,该实体存储为 json 文档,并且字段 customData、customMultipleData、rcfData 从 json 到对象的转换由 spring data 处理。

为了将它存储在 postgresql 中,我想到了使用以下表结构,利用 postgresqls jsonb 类型。

CREATE TABLE ebbin.beneficiary_data
(
    id integer NOT NULL DEFAULT nextval('bms_v21.beneficiary_data_id_seq'::regclass),
    beneficiary_id integer NOT NULL,
    custom_data jsonb,
    custom_multiple_data jsonb,
    last_updated_on timestamp(3) without time zone,
    CONSTRAINT beneficiary_data2_pkey PRIMARY KEY (id)
)
WITH (
    OIDS = FALSE
)
TABLESPACE pg_default;

为了处理两个 jsonb 类型,我实现了两个自定义休眠用户类型

JSONBCustomDataUserType.java

public class JSONBCustomDataUserType extends CollectionUserType implements ParameterizedType {

    private static final String JSONB_TYPE = "jsonbCustomData";
    public static final String CLASS = "CLASS";

    @Override
    public Class<Object> returnedClass() {
        return Object.class;
    }

    @Override
    public int[] sqlTypes() {
        return new int[] { Types.JAVA_OBJECT };
    }

    // ... implementations for nullSafeGet, nullSafeSet ...
}

JSONBCustomMultipleDataUserType.java

public class JSONBCustomMultipleDataUserType extends CollectionUserType implements ParameterizedType {

    private static final String JSONB_TYPE = "jsonbCustomData";
    public static final String CLASS = "CLASS";

    @Override
    public Class<Object> returnedClass() {
        return Object.class;
    }

    @Override
    public int[] sqlTypes() {
        return new int[] { Types.JAVA_OBJECT };
    }

    // ... implementations for nullSafeGet, nullSafeSet ...
}

我的 postgresql 实体现在是 BeneficiaryData.java

@TypeDefs({
    @TypeDef(name = "jsonbCustomData", typeClass = JSONBCustomDataUserType.class, 
             parameters = {@Parameter(name = JSONBCustomDataUserType.CLASS, value = "java.util.Map")}), 
    @TypeDef(name = "jsonbCustomMultipleData", typeClass = JSONBCustomMultipleDataUserType.class, 
             parameters = {@Parameter(name = JSONBCustomMultipleDataUserType.CLASS, value = "java.util.Map")})
})
@Entity
@Table(name = "beneficiary_data")
public class BeneficiaryData extends BaseEntity {

    @Id
    @GeneratedValue(strategy = IDENTITY)
    @Column(name = "id", unique = true, nullable = false)
    private Integer id;

    @Column(name = "beneficiary_id", nullable = false)
    private Integer beneficiaryId;

    @Type(type = "jsonbCustomData")
    @Column(name = "custom_data", nullable = true)
    private Map<Integer, Object> customData;

    @Type(type = "jsonbCustomMultipleData")
    @Column(name = "custom_multiple_data", nullable = true)
    private Map<Integer, List<Integer>> customMultipleData;


    @Temporal(TemporalType.TIMESTAMP)
    @Column(name = "last_updated_on", length = 19)
    private Date lastUpdatedOn;

    public BeneficiaryData() {
    }

    // ...
}

还创建了一个自定义 postgresql 方言,以便可以注册新的用户类型。

CustomPostgreSqlDialect.java

public class CustomPostgreSqlDialect extends PostgreSQL95Dialect {

    public CustomPostgreSqlDialect() {
        super();
        this.registerColumnType(Types.JAVA_OBJECT, "jsonbCustomData");
        this.registerColumnType(Types.JAVA_OBJECT, "jsonbCustomMultipleData");
    }
}

但是,当我尝试使用 session.save() 保存实体时,出现以下错误。

org.springframework.dao.InvalidDataAccessResourceUsageException: could not insert: [com.tcs.bms.persistence.entity.BeneficiaryData];
.
.
.
Caused by: org.postgresql.util.PSQLException: Unknown type jsonbCustomData.

我猜这与我将列类型 JAVA_OBJECT 注册到 jsonbCustomData 和 jsonbCustomMultipleData 有关

我这样说是因为当我尝试仅使用 jsonbCustomData 用户类型时(在注释掉实体中的 customMultipleData 字段并从表中删除之后),我能够成功插入、更新和获取数据。

知道我做错了什么吗?

【问题讨论】:

    标签: java postgresql hibernate spring-mvc jsonb


    【解决方案1】:

    聚会可能有点晚了,但在不知道问题的确切解决方案的情况下,我有两个建议:

    1. 根据您的未知类型的 PSQLException,您的方言可能需要如下所示:
    公共类 CustomPostgreSqlDialect 扩展 PostgreSQL95Dialect { 公共 CustomPostgreSqlDialect() { 极好的(); this.registerColumnType(Types.JAVA_OBJECT, "jsonb"); } }

    ...正如javadoc 所述,第二个属性必须是“数据库类型名称”& PSQL 不会知道关于名为“jsonbCustom..”的类型的任何信息

    1. 甚至不要编写自定义方言!我不知道您扩展的CollectionUserType 的内容,但我有一个设置非常相似的工作项目(Spring 4.3.14 / Hibernate 5.2.12 / PSQL 9.5),我所要做的就是创建自定义 UserTypes &将这些类型注册/注释到类及其相应的字段中。如果您愿意,我很乐意分享代码。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2017-05-30
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-05-14
      • 2017-10-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多