【问题标题】:Hibernate 4 - What should replace deprecated @MapKey to map a Map collection while Key is a customized Hibernate UserTypeHibernate 4 - 当 Key 是自定义的 Hibernate UserType 时,应该用什么替换已弃用的 @MapKey 来映射 Map 集合
【发布时间】:2015-11-25 06:09:46
【问题描述】:

考虑以下两个表:

| 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 的困难在于将用户类型 AttributeKeyHbm 作为 attributesUserHbm 中的键

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

所以我的问题是:

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

【问题讨论】:

  • 为什么不将AttributeKeyHbm 标记为@Embeddable?在这种情况下,您可以将@Column 添加到类的属性中。
  • @TobiasLiefke 你能详细说明一下吗?
  • 什么不清楚?你读过Hibernate documentation of Maps吗?

标签: java hibernate hibernate-mapping


【解决方案1】:

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

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

异常表示key UserType 的列号与key 列不同。 我找不到 @MapKeyColumns 但我尝试了 @MapKeyColumn(name="id") 并使 AttributeKeyHbm 只有“id”并且它有效。 所以一切都是为了找到类似MapKeyColumns的注解。

【讨论】:

    猜你喜欢
    • 2012-02-09
    • 1970-01-01
    • 1970-01-01
    • 2017-06-06
    • 2023-03-26
    • 2017-03-12
    • 2017-10-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多