在 hibernate postgresql 中为 jsonb 列创建自定义用户类型



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

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

受益人数据.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 文档,并且从 json 到字段 customData、customMultipleData、rcfData 的对象转换由 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 类型,我实现了两个 cutom hibernate UserType

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 实体现在是受益人数据.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 字段并从表中删除后(,我能够成功插入、更新和获取数据。

知道我做错了什么吗?

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

  1. 根据未知类型的 PSQLException,您的方言可能需要如下所示:
public class CustomPostgreSqlDialect extensions PostgreSQL95Dialect { public CustomPostgreSqlDialect(( { 超级((; this.registerColumnType(Types.JAVA_OBJECT, "jsonb"(; } }

...正如Javadoc所说,第二个属性必须是">数据库类型名称",PSQL对名为"jsonbCustom"的类型一无所知。

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

最新更新