Hibernate嵌入式列表映射与标识符

时间:2014-03-19 14:12:47

标签: java hibernate jpa annotations hibernate-mapping

我有一个具有可嵌入地址的Person实体,它们之间存在一对多的关系(一个人可以有多个地址)。当前的映射是这样的:

@Embeddable
public class Address {  
    // ... attributes
}

@Entity
public class Person {
    @ElementCollection(fetch = FetchType.EAGER)
    @JoinTable(name = "Person_addresses", joinColumns = @JoinColumn(name = "personid")
    )
    /*
    Attribute ovverrides with annotations
    */
    private java.util.Set<Address> addresses = new java.util.HashSet<Address>();    
}

使用此注释意味着在数据库中我有一个Person_addresses表,其中包含所有地址属性和personid。但这也意味着如果我有一个人有地址列表并更新地址列表,Hibernate会删除所有相关记录并再次插入它们(修改后的记录)。

据我所知,有一种方法可以在此表中为每条记录创建一个主键 - 在这种情况下,hibernate可以决定需要更新列表中的哪个项目。所以我的问题是,如何在加入表中映射带有标识符的可嵌入列表? (我希望我想要的是可以理解的:))。

2 个答案:

答案 0 :(得分:2)

http://en.wikibooks.org/wiki/Java_Persistence/ElementCollection#Primary_keys_in_CollectionTable

  

JPA 2.0规范没有提供定义Id的方法   可嵌入的。但是,删除或更新元素   ElementCollection映射通常需要一些唯一键。   否则,在每次更新时,JPA提供程序都需要删除   来自实体的CollectionTable的所有内容,然后插入   价值回来了。因此,JPA提供商很可能会认为   Embeddable中所有字段的组合都是独一无二的   与外键组合(JoinColumn(s))。然而,这可以   如果Embeddable很大,那么效率低下,或者说不可行   复杂。某些JPA提供程序可能允许在中指定Id   可嵌入,解决此问题。请注意,在这种情况下,Id只需要   对于集合而言是唯一的,而不是表,就像外键一样   包括在内。有些人还可能允许CollectionTable上的唯一选项   用于此。否则,如果您的Embeddable很复杂,您可以   考虑将其变为实体并改为使用OneToMany。

就这样,它无法完成。

答案 1 :(得分:2)

正如maestro的回复所暗示的,唯一可移植的解决方案是将其转换为使用实体和一对多。

也就是说,Hibernate有一个名为&#34; id bag&#34;的非规范功能。它允许您使用每行的标识符映射基本或可嵌入的集合,从而为您提供所需的有效更新:

@Entity
public class Person {
    @CollectionId( columns={"address_id"}, type="int", generator="increment" )
    @ElementCollection(fetch = FetchType.EAGER)
    @JoinTable(name = "Person_addresses", joinColumns = @JoinColumn(name = "personid"))
    private java.util.List<Address> addresses = new java.util.ArrayList<Address>(); 
}

请注意,从Set切换到List。还要注意生成的表结构......看起来很像实体;)