【问题标题】:How do I auto-generate IDs for an @ElementCollection when it is a java.util.Map?当 @ElementCollection 是 java.util.Map 时,如何为它自动生成 ID?
【发布时间】:2014-10-01 15:29:45
【问题描述】:

我正在使用 MySQL 5.5.37、JPA 2.0 和 Hibernate 4.1.0.Final(如果能解决我的问题,我愿意升级)。我有以下实体……

@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", joinColumns=@JoinColumn(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", joinColumns=@JoinColumn(name="url_id"))
private Set<UrlProperty> properties;

但它导致了异常,“org.hibernate.MappingException: Foreign key (FK24E4A95BB0648B:url_property [properties_id])) must have the same number of columns as the referenced primary key (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;

【问题讨论】:

  • url_property“id”列将是与其相关的 Url 类的“id”(即 FK)。您不会为集合表生成它们。使用地图时,我希望“url_id”和“property_name”是“url_property”表的复合 PK。
  • 好的,那么我如何告诉 JPA 按照您的建议生成复合主键?现在,生成的密钥似乎只是空字符串。
  • 应该是自动的,不需要进一步配置......或者至少它适用于我的 JPA 提供程序(DataNucleus)。

标签: mysql hibernate jpa jpa-2.0


【解决方案1】:

您只告诉了 JPA 表中的 3 个字段(“property_name”、“property_value”和“url_id”),因此它无法知道用作 pk 的第 4 个字段。由于它不是实体,因此它没有维护的身份。选项是:

1) 将“url_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。不过看起来没什么用,因为应用程序永远不会知道该字段。

【讨论】:

  • 对于您的第一个建议,我在我的问题中尝试了上述方法,但结果是“org.hibernate.MappingException: Foreign key (FK24E4A95BB0648B:url_property [properties_id])) must have the same number of columns作为引用的主键 (url_property [url_id,properties_id])”异常。有什么想法吗?
  • 对于#1,我建议使用 OneToMany 而不是元素集合,如提供的链接中的第一个示例中所述。例外是因为您使用的是 ElementCollection,这意味着该对象没有自己的 ID,必须使用其父级的身份。删除 ElementCollection、Column 和 CollectionTable 注释并将它们替换为 OneToMany(mappedBy="SubdomainUrl") 将解决问题
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-02-07
  • 1970-01-01
  • 2021-11-08
  • 2011-01-11
相关资源
最近更新 更多