Hibernate 4 – 什么应该替换弃用的@MapKey来映射Map集合,而Key是一个自定义的Hibernate UserType

考虑以下两个表:

| User | UserAttribute | |---------- |-------------------| | userId(PK)| attributeId(PK) | | firstName | userId | | lastName | name | | other | locale | | active | value | 

在原始的hibernate-3.2.2一对多双向关系工作正常:

 @Entity @Table(name = "User") public class UserHbm { @Id @GeneratedValue(generator = "id-generator") @Column(name = "userId") private long id; @Column private String firstName; @Column private String lastName; @Column private String other; @Column private boolean active = true; @OneToMany (mappedBy = "user", cascade = CascadeType.ALL, fetch=FetchType.LAZY) @MapKey(columns = { @Column(name = "name"), @Column(name = "locale") }) @Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN) private Map attributes = null; //other methods, getter & setting, etc... } 

 @Entity @Table(name = "UserAttribute") public class UserAttributeHbm { @Id @GeneratedValue(generator = "id-generator") @Column(name="attributeId") private long id; @ManyToOne(cascade = {CascadeType.PERSIST, CascadeType.MERGE} ) @JoinColumn(name="userId") private UserHbm user; @Column private String name; @Column private Locale locale = Locale.ENGLISH; @Column private String value; // other methods... } 

 public class AttributeKeyHbm implements UserType { protected static int[] SQL_TYPES = { Types.VARCHAR, Types.VARCHAR }; private String name; private Locale locale; public AttributeKeyHbm(String name, Locale locale) { this.name = name; this.locale = locale; } //other override methods, assemble, deepCopy & nullSafeGet, etc... } 

使hibernate从3.2.2迁移到4.3.11困难的原因是将UserType AttributeKeyHbm作为UserHbmattributesUserHbm

AttributeKeyHbm是Hibernate的服务型UserType,分别包含UserAttributeHbmnamelocal两列。

由于不推荐使用 hibernate注释@MapKey ,我尝试逐个使用以下注释来替换原来的@MapKey

 @MapKeyType(value=@Type(type="com.xxx.xxx.AttributeKeyHbm")) @MapKeyJoinColumns(value={ @MapKeyJoinColumn(name = "name"), @MapKeyJoinColumn(name = "locale")}) @MapKeyJoinColumn(name = "AttributeKeyHbm") 

但这一切都以这些例外结束:

 org.hibernate.MappingException: collection index mapping has wrong number of columns: com.xxx.xxx.UserHbm.attributes type: com.xxx.xxx.AttributeKeyHbm 

所以我的问题是:

  • 如何使用hibernate-4.3.11UserHbm实现相同的function,因为不能放弃AttributeKeyHbm ,因为它已经被其他API大量使用了。
  • 由于AttributeKeyHbm有两列,它是否正确或足以实现接口UserType而不是CompositeUserType

首先,它应该用MapKeyClass(JPA)替换MapKeyType(Hibernate),或者只是删除它,因为Hibernate将自动检测。

在这种情况下,将跳过MapKeyJoinColumns / MapKeyJoinColumn,请参阅JPA文档https://docs.oracle.com/javaee/6/api/javax/persistence/MapKeyJoinColumn.html我猜它们仅用于实体。

exception表示关键UserType的列号与键列不同。 我找不到@MapKeyColumns但是我尝试了@MapKeyColumn(name =“id”)并且让AttributeKeyHbm只有“id”并且它有效。 所以一切都是找到类似MapKeyColumns的注释。