ses*_*ses 0 database hibernate jpa playframework
我使用JPA-> Hibernate.PlayFramework.我想要有关系.
Category - 1:n -> Tag
Run Code Online (Sandbox Code Playgroud)
每个类别都可以有许多标签,但标签不知道它.
所以,我喜欢这样:
Run Code Online (Sandbox Code Playgroud)@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();
}
Run Code Online (Sandbox Code Playgroud)
结果是:
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)
Run Code Online (Sandbox Code Playgroud)
似乎cat2.save()尝试做更多然后它应该
如果使用merge()而不是save(),它的效果很好:
cat2.merge();
Run Code Online (Sandbox Code Playgroud)
但为什么?
我已经解决了这个问题.问题在于,我没有使用那个注释.所以我只是将@OneToMany改为@ManyToMany而且vo更改了 - 没有任何限制了.
但是如果说OneToMany然后似乎在数据库级别上有一个独特的限制,这阻止我们将不唯一的值放入tags_id.因此,我们无法将相同的标记放在一个类别中.即它想要许多标签的一个类别,但如果标签已经"使用" - 没办法..我试图在@JoinTable中放置unique = true/false - > @JoinColumn - 但它没有帮助.对我来说,它仍然很奇怪,但至少目前的问题是固定的.
你混淆了两个概念:主键和外键.
只有一个PK,但FK只是意味着"在其他一些表中必须有一个带有此ID的元素".FK不限制唯一性.
[编辑]你的问题是你正在混合实体.你是如何得到tag1这是由返回save()?
这个实体必须是你从Hibernate获得的实体,而不是来自的实体new.即使它看起来很疯狂,你必须这样做save():
session.save(tag);
return session.load(tag.getId());
Run Code Online (Sandbox Code Playgroud)
这样,您就可以获得由Hibernate管理的实体.只有当实体由Hibernate管理时,Hibernate才知道它何时必须保存实体以及何时已经保存.
所以当你cat2.tags.add(tag1);在上面的例子中做的时候,Hibernate认为"哦,我对这个标签一无所知,它必须是一个新标签".
并尝试再次保存标记.
| 归档时间: |
|
| 查看次数: |
7995 次 |
| 最近记录: |