Hibernate 4 - 当Key是一个自定义的Hibernate UserType时,应该替换弃用的@MapKey以映射Map集合

时间:2015-08-31 08:51:07

标签: java hibernate hibernate-mapping

考虑以下两个表:

| 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<AttributeKeyHbm, UserAttributeHbm> 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 AttributeKeyHbmattributesUserHbm的关键

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

由于hibernate注释@MapKeydeprecated,我尝试逐个使用以下注释,以替换原始@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

所以我的问题是:

  • 如果UserHbm无法放弃hibernate-4.3.11,如何在AttributeKeyHbm中使用AttributeKeyHbm实现相同的功能,因为它已被其他API严重使用。< / LI>
  • 由于UserType有两列,是否正确或足以实现接口CompositeUserType而不是'ITEMS.itemid'

1 个答案:

答案 0 :(得分:0)

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

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

异常表示关键UserType的列号与键列不同。 我找不到@MapKeyColumns但我尝试了@MapKeyColumn(name =&#34; id&#34;)并且让AttributeKeyHbm只有&#34; id&#34;它的工作原理。 所以一切都是找到类似MapKeyColumns的注释。