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

Java 在hibernate postgresql中为jsonb列创建自定义用户类型,java,postgresql,hibernate,spring-mvc,jsonb,Java,Postgresql,Hibernate,Spring Mvc,Jsonb,我正在尝试将我的SpringMVC项目数据库从mongodb迁移到postgresql。 Spring版本4.3.8.0发布 Hibernate版本5.2.10.Final Postgresql数据库版本为9.6 我正在尝试为以下实体实现创建、读取和更新操作 受益人数据.java @Document(collection = "beneficiary_data") public class BeneficiaryData extends BaseEntity { @Id pri

我正在尝试将我的SpringMVC项目数据库从mongodb迁移到postgresql。 Spring版本4.3.8.0发布 Hibernate版本5.2.10.Final Postgresql数据库版本为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() {
    }
}
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 ...
}
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 ...
}
@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() {
    }

    // ...
}
public class CustomPostgreSqlDialect extends PostgreSQL95Dialect {

    public CustomPostgreSqlDialect() {
        super();
        this.registerColumnType(Types.JAVA_OBJECT, "jsonbCustomData");
        this.registerColumnType(Types.JAVA_OBJECT, "jsonbCustomMultipleData");
    }
}
为了处理这两种jsonb类型,我实现了两种cutom hibernate用户类型

JSONBCustomDataUserType.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() {
    }
}
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 ...
}
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 ...
}
@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() {
    }

    // ...
}
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_对象同时注册到jsonbCustomData和jsonbCustomMultipleData有关

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


知道我做错了什么吗?

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

  • 根据未知类型的PSQLException,您的方言可能需要如下所示:
  • 公共类CustomPostgreSqlDialogue扩展了PostgreSql95Dialogue{ 公共CustomPostgreSqlDialogue(){ 超级(); registerColumnType(Types.JAVA_对象,“jsonb”); } } …如前所述,第二个属性需要是“数据库类型名称”&PSQL不知道关于名为“jsonbCustom…”的类型的任何信息

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