Hibernate 4 - 什么应该替代弃用的@MapKey来映射一个Map集合,而Key是一个定制的Hibernate UserType [英] Hibernate 4 - What should replace deprecated @MapKey to map a Map collection while Key is a customized Hibernate UserType

查看:252
本文介绍了Hibernate 4 - 什么应该替代弃用的@MapKey来映射一个Map集合,而Key是一个定制的Hibernate UserType的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

考虑以下两个表:

  |用户| UserAttribute | 
| ---------- | ------------------- |
|用户ID(PK)| attributeId(PK)|
| firstName | userId |
| lastName |名称|
|其他| locale |
|活动|值|

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

  @Entity 
@Table (name =User)
public class UserHbm {

@Id
@GeneratedValue(generator =id-generator)
@Column(name = userId)
私人长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;

//其他方法,getter&设置等...
}






<$


@GeneratedValue($ name)

@Table(name =UserAttribute)
public class UserAttributeHbm {

@Id
@GeneratedValue generator =id-generator)
@Column(name =attributeId)
私人长ID;

@ManyToOne(cascade = {CascadeType.PERSIST,CascadeType.MERGE})
@JoinColumn(name =userId)
private UserHbm user;

@Column
私人字符串名称;

@Column
私有语言环境locale = Locale.ENGLISH;

@Column
私有字符串值;

//其他方法...
}






  public class AttributeKeyHbm implements UserType {

protected static int [] SQL_TYPES = {Types.VARCHAR,Types.VARCHAR};

私人字符串名称;

私人语言区域设置;

public AttributeKeyHbm(String name,Locale locale){
this.name = name;
this.locale = locale;
}

//其他重写方法,汇编,deepCopy& nullSafeGet等...
}

是什么让 hibernate 从3.2.2迁移到4.3.11作为属性 AttributeKeyHbm c> UserHbm



AttributeKeyHbm 是一个服装的用户类型的Hibernate,包含 UserAttributeHbm 名称本地

由于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:集合索引映射的列数错误:com.xxx.xxx.UserHbm.attributes类型:com.xxx.xxx.AttributeKeyHbm 

所以我的问题是:


  • 如何在 UserHbm hibernate-4.3.11 ,假设 AttributeKeyHbm couldn不会被放弃,因为它已被其他API大量使用。
  • 由于 AttributeKeyHbm 有两列,是正确的还是足够执行接口 UserType 而不是 CompositeUserType




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



该异常意味着密钥UserType的列号与密钥列不同。
我找不到@MapKeyColumns,但我试过@MapKeyColumn(name =id),并使AttributeKeyHbm只有id,它的工作原理。
因此,所有的都是找到类似MapKeyColumns的注释。


Considering the following two tables:

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

In original hibernate-3.2.2, the one-to-many bidirectional relationship works fine:

@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...
}

What makes hibernate migration from 3.2.2 to 4.3.11 difficult is the costumed UserType AttributeKeyHbm as a key of attributes in UserHbm

AttributeKeyHbm is a costumed UserType of Hibernate, containing two columns from UserAttributeHbm, name and local respectively.

Since hibernate annotation @MapKey is deprecated, I've tried to use the following annotations one by one, to replace the original @MapKey:

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

But it all ends up with this exceptions:

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

So my questions are:

  • How to implement the same function in UserHbm with hibernate-4.3.11, given that AttributeKeyHbm couldn't be abandoned cause it's already used by other API heavily.
  • As AttributeKeyHbm has two columns, is it correct or enough to implement interface UserType instead of CompositeUserType

解决方案

First of all, it should replace MapKeyType(Hibernate) with MapKeyClass(JPA) or just remove it since Hibernate will auto detect.

And MapKeyJoinColumns/MapKeyJoinColumn will be skipped in this case, refer to the JPA document https://docs.oracle.com/javaee/6/api/javax/persistence/MapKeyJoinColumn.html I guess they're used for entity only.

The exception means key UserType's column number is not the same with the key column. I can't find @MapKeyColumns but I tried @MapKeyColumn(name="id") and make AttributeKeyHbm only has "id" and it works. So all is to find the MapKeyColumns-like annotation.

这篇关于Hibernate 4 - 什么应该替代弃用的@MapKey来映射一个Map集合,而Key是一个定制的Hibernate UserType的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆