相关文章推荐
还单身的松鼠  ·  postgresql - psql: ...·  1 年前    · 
豁达的企鹅  ·  %E5%BD%A9%E7%A5%A8%E6% ...·  1 年前    · 
Collectives™ on Stack Overflow

Find centralized, trusted content and collaborate around the technologies you use most.

Learn more about Collectives

Teams

Q&A for work

Connect and share knowledge within a single location that is structured and easy to search.

Learn more about Teams 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();

The result is:

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)

It seems that cat2.save() try to do more then it should

If if use merge() instead of save() it works good:

 cat2.merge();

BUT WHY?

I have fixed the problem. The problem was in that, that I used NOT THAT annotation. So i just changed @OneToMany to @ManyToMany and voilà - No any restrictions anymore.

But if saying about the OneToMany then it seems there was a unique-restriction on database-level which prevented us to put not-unique values to tags_id. Therefore we could not put same tag to One category. I.e. it wanted One category for Many tags, but if tags were already 'used' - no way.. I tried to put unique=true/false in @JoinTable -> @JoinColumn - but it does not help. For me it's still strange, but at least current problem was fixed.

You're mixing up two concepts: Primary key and foreign key.

There can be only one PK but FK just means "there must be an element with this ID in some other table". FK doesn't constrain uniqueness.

[EDIT] Your problem is that you're mixing entities. How did you get the tag1 which is returned by save()?

This entity must be one which you get from Hibernate, not the result from new. Even if it looks insane, you must do this in save():

session.save(tag);
return session.load(tag.getId());

This way, you get an entity that is managed by Hibernate. Only when the entity is managed by Hibernate, Hibernate knows when it has to save the entity and when it has already been saved.

So when you do cat2.tags.add(tag1); in your example above, Hibernate thinks "oh, I don't know anything about this tag, it must be a new one".

And tries to save the tag again.

yes. but my error is: Cannot add or update a child row: a foreign key constrains fails ..... FOREIGN KEY ('tags_id') references 'Tag('id')' – ses Apr 29, 2011 at 13:07 The error means the tag wasn't written to the TAB table. Did you properly commit after adding the tag? if you run a plain SQL query, can you read the tag from the DB? – Aaron Digulla Apr 29, 2011 at 16:06 Tag tag1 = new Tag("tag1").save(); this is managed by PlayFramework. When it returns tag1 here it's already managed by hibernate - it has id, tied with session etc. No he does not think 'it must be a new one' here. Should not - because tag1 saved and returned by play's save(). – ses Apr 29, 2011 at 21:08 What makes you think that tag1 is tied to the session? The error says it is not. That's also why merge() solves the problem: It attaches the entity to the session. – Aaron Digulla May 2, 2011 at 10:24 Even if i use SQL clause 'insert into' in my sql editor - it's impossible to insert data to third table category_tag(category_id, tags_id) if tags_id is going to be duplicated. That why i think the problem is not in the session. – ses May 2, 2011 at 10:36

Thanks for contributing an answer to Stack Overflow!

  • Please be sure to answer the question. Provide details and share your research!

But avoid

  • Asking for help, clarification, or responding to other answers.
  • Making statements based on opinion; back them up with references or personal experience.

To learn more, see our tips on writing great answers.