一对多和重复条目

时间:2011-04-29 12:46:38

标签: database hibernate jpa playframework

我使用JPA-> Hibernate。 PlayFramework。我想要有关系。

 Category - 1:n -> Tag

每个类别都有很多标签,但标签不知道它。

所以,我喜欢这样:

@Entity
public class Category ... {
    @OneToMany
    public List<Tag> tags = new LinkedList<Tag>();
}

我有测试:

@Test     public void playWithTags(){

    Tag tag1 = new Tag("tag1").save(); // managed by playframework

    Category cat1 = new Category("cat1");
    cat1.tags.add(tag1);
    cat1.save();

    // check if tag1 and cat1 were saved  
    assertEquals(1, Tag.count());
    assertEquals(1, Category.count());

    Category cat2 = new Category("cat2");
    cat2.tags.add(tag1);
    cat2.save();

}

结果是:

16:18:01,555 ERROR ~ Duplicate entry '1' for key 'tags_id'
16:18:01,555 ERROR ~ Could not synchronize database state with session
org.hibernate.exception.ConstraintViolationException: Could not execute JDBC batch update
    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:96)
    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelp
....
java:908)
    at java.lang.Thread.run(Thread.java:619)
Caused by: java.sql.BatchUpdateException: Duplicate entry '1' for key 'tags_id'
    at com.mysql.jdbc.PreparedStatement.executeBatchSerially(PreparedStatement.java:2020)

似乎cat2.save()尝试做的更多然后应该

如果使用merge()而不是save(),那么效果很好:

 cat2.merge();

但是为什么?

2 个答案:

答案 0 :(得分:6)

我已经解决了这个问题。问题在于,我没有使用那个注释。所以我只是将@OneToMany改为@ManyToMany而且vo更改了 - 没有任何限制了。

但是如果说OneToMany然后似乎在数据库级别上有一个独特的限制,这阻止我们将不唯一的值放到tags_id上。因此,我们无法将相同的标记放在一个类别中。即它想要许多标签的一个类别,但如果标签已经“使用” - 没办法..我试图在@JoinTable中放置unique = true / false - &gt; @JoinColumn - 但它没有帮助。对我来说,它仍然很奇怪,但至少目前的问题是固定的。

答案 1 :(得分:5)

你混淆了两个概念:主要键和外来键。

只有一个PK,但FK只是意味着“在其他一些表中必须有一个带有此ID的元素”。 FK并不限制唯一性。

[编辑]你的问题是你正在混合实体。您是如何获得tag1返回的save()的?{/ p>

此实体必须是您从Hibernate获得的实体,而不是new的结果。即使看起来很疯狂,也必须在save()

中执行此操作
session.save(tag);
return session.load(tag.getId());

这样,您就可以获得由Hibernate管理的实体。只有当实体由Hibernate管理时,Hibernate才知道何时需要保存实体以及何时保存实体。

因此,当您在上面的示例中执行cat2.tags.add(tag1);时,Hibernate会认为“哦,我对此标记一无所知,它必须是新标记”。

并尝试再次保存标记。