【问题标题】:Prevent duplicate entry for unique constraint防止重复输入唯一约束
【发布时间】:2014-04-08 23:48:42
【问题描述】:

我正在尝试在我的 MySQL 数据库中保存与文章相关的标签。这两列之间的关系是 1:N。每个项目都有一个自动生成的密钥。标签的名称是唯一的。

如果我插入带有现有标签的新文章,我会收到唯一约束的重复条目异常 (MySQLIntegrityConstraintViolationException)。这是我的两个实体:

Article.java

@Entity
public class Article implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @OneToMany(cascade = CascadeType.ALL)
    @JoinTable
    private Set<Tag> tags = new HashSet<Tag>();

    /* getter and setter */
}

标签.java

@Entity
public class Tag implements Serializable {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private long id;

    @Column(unique = true)
    private String name;

    /* getter and setter */
}

Hibernate 生成以下表格articletagarticle_tag。第一篇文章的记录是正确的。

我使用以下代码插入新文章(仅用于测试):

Article article = new Article();
Tag tag = new Tag();
/* set the values */
EntityManager em = EMF.getInstance().get();
em.getTransaction().begin();
em.merge(article);
em.getTransaction().commit();

如何让 JPA 使用文章的现有标签而不是创建新标签。如何正确设置这些组件之间的关系?

【问题讨论】:

  • 我假设The name of a tag is unique. 表示在包含文章和标签的表格中,标签列被标记为唯一,这实际上意味着如果您尝试插入带有另一个标签的不同文章文章已经有会抛出你的异常。解决方案是将标签存储在一个单独的表中,它们是唯一的,然后通过外键插入对文章表中各种标签的引用。 TL;DR 不要在Articles 中包含Tags,insead 包含可以映射到Tags 的引用
  • 没错,我正在这样做。我有第三列article_tag,其中包含文章的Id 和标签。每个文章和标签都存储在自己的表中。
  • 尝试将HashSet 对象更改为包含代表Tag ID 的longs。之后,当您需要检查Article 的标签时,您检索存储在Article 记录中的long,然后查找Tag 表以将标签与您从Article 记录中获得的ID 匹配。

标签: java mysql hibernate jpa unique


【解决方案1】:

一般来说文章和标签之间的关系是多对多的关系,因为一篇文章可能有许多标签,每个标签都可以在许多文章。

要指示 多对多 关系,需要 @ManyToMany 注释。

另外为了明确一点,在 OP 中,它表示 单向 一对多关系,因为 @JoinTable 注释具有被多方面使用。这就是创建连接表的原因。此外,如果在Tag 类中使用@ManyToOne 注释,则多对一 将是另一个单向 关系。 请小心,因为它们将被视为具有可能奇怪行为的两个独立的单向关系,并且任何配置都不会影响两个实体,因为它不是双向关系。

最后,如果需要一对多单向关系又需要复用标签,则需要根据它们的名字来检索它们,以便它们有正确的记录id 然后将其设置为Article 实例。如果您尝试设置 Tag 的新实例,该实例将没有记录 id 但名称已存在,则 jpa 提供程序将尝试插入新标签并抛出唯一约束异常,因为重复标签姓名。还需要删除 article_tag 表中引用的任何唯一约束 tag_id

【讨论】:

  • 唯一约束是否适用于@ManyToMany
  • @hofmeister 如果您在谈论 Tag 表是的,就像您提供的帖子中一样,标签名称应该有一个唯一的约束。但是在join table article_tag 关于tag_id 否,在这两种情况下都不应该有唯一的约束,因为标签端是many,无论是多对多还是单向一对多,并且tag id 会关联多次,因此同一个 id 可能会出现在多条记录中。
  • 嗯。抱歉,但我仍然不知道如何将具有唯一值的实体与其他实体连接起来。我用 mappedBy 尝试了 @ManyToMany,但仍然得到唯一的异常。
  • @hofmeister 可能我有点困惑,无论你使用@ManyToMany还是@OneToMany,都需要先从db中检索你想要关联的标签,使用jpa,然后设置到文章。 tag 实例需要有正确的记录 id 才能让 jpa 将它与现有的托管实体相关联,否则它将尝试在 tag 表中插入一条具有相同 tag 名称的新记录并抛出异常。
猜你喜欢
  • 2017-08-13
  • 2021-12-06
  • 2012-11-06
  • 1970-01-01
  • 2012-04-03
  • 1970-01-01
  • 2015-05-31
  • 1970-01-01
  • 2019-05-03
相关资源
最近更新 更多