2014-10-01 55 views
0

我使用MySQL 5.5.37,JPA 2.0和Hibernate 4.1.0.Final(如果它解决了我的问题,我愿意升级)。我有以下实体...如何在@ElementCollection是java.util.Map时自动生成ID?

@Entity 
@Table(name = "url") 
public class Url implements Serializable 
{ 

    … 
    @ElementCollection(fetch=FetchType.EAGER) 
    @MapKeyColumn(name="property_name") 
    @Column(name="property_value") 
    @CollectionTable(name="url_property", [email protected](name="url_id")) 
    private Map<String,String> properties; 

的“url_property”表有一个ID(主键)列,也许是这个原因,当我创建具有多个属性的一个新的URL的实体,我的脚异常

[ERROR]: org.hibernate.engine.jdbc.spi.SqlExceptionHelper - Duplicate entry '' for key 'PRIMARY' 

保存。有谁知道我必须做什么来为我的url_property表自动生成ID?我宁愿不写一个触发器,而是做一些JPA,或者至少是Hibernate的批准。

编辑:每在回答第一个建议,我尝试

@ElementCollection(fetch=FetchType.EAGER) 
@Column(name="property_value") 
@CollectionTable(name="url_property", [email protected](name="url_id")) 
private Set<UrlProperty> properties; 

,但它造成了例外,“org.hibernate.MappingException:外键(FK24E4A95BB0648B:url_property [properties_id]))必须与引用的主键(url_property [url_id,properties_id])具有相同的列数“”。

我UrlProperty实体

@Entity 
@Table(name = "url_property") 
public class UrlProperty 
{ 

    @Id 
    @GeneratedValue(generator = "uuid-strategy") 
    private String id; 

    @ManyToOne(fetch=FetchType.EAGER) 
    @JoinColumn(name="URL_ID") 
    private SubdomainUrl url; 

    @Column(name="PROPERTY_NAME") 
    private String propertyName; 

    @Column(name="PROPERTY_VALUE") 
    private String propertyValue; 
+1

url_property“id”列将成为它所涉及的Url类的“id”(即FK)。您不会为收集表生成它们。当使用Map时,我希望“url_id”和“property_name”是“url_property”表的组合PK。 – 2014-10-01 15:37:36

+0

好吧,那么如何让JPA根据您的建议生成复合主键?现在看来,生成的关键字只是空字符串。 – Dave 2014-10-01 15:56:20

+0

应该是自动的,不需要进一步配置...或者至少它是用于我的JPA提供程序(DataNucleus)。 – 2014-10-01 16:03:19

回答

0

你只告诉JPA在表(“PROPERTY_NAME”,“PROPERTY_VALUE”和“url_id”)约3个字段,所以它无法了解第四届方式字段用作pk。由于它不是一个实体,因此它没有维护的身份。选项是:

1)将“url_property”表映射到Property实体,该实体将具有ID,值和对Url的引用。然后Url将对Property类具有1:M引用,并且仍可以键入名称。 http://wiki.eclipse.org/EclipseLink/Examples/JPA/2.0/MapKeyColumns有一个示例

2)更改您的表以删除ID字段,而是使用“property_name”,“property_value”和“url_id”作为主键。

3)设置一个触发器来填充ID。虽然应用程序永远不知道该字段,但似乎并不有用。

+0

对于你的第一个建议,我在我的问题中尝试了上面的内容,但它导致了一个“org.hibernate.MappingException:外键(FK24E4A95BB0648B:url_property [properties_id]))必须与引用的主键具有相同的列数(url_property [url_id,properties_id])“异常。有任何想法吗? – Dave 2014-10-01 20:33:22

+0

对于#1,我建议使用OneToMany而不是元素集合,如提供的链接的第一个示例中所述。例外是因为您使用的是ElementCollection,这意味着该对象没有自己的ID并且必须使用其父标识。删除ElementCollection,Column和CollectionTable注释并用OneToMany替换它们(mappedBy =“SubdomainUrl”)将解决问题 – Chris 2014-10-02 12:58:11