Save() does not save manyToMany relationship

2,271 views
Skip to first unread message

Quentin Volt

unread,
Aug 5, 2013, 11:06:57 AM8/5/13
to eb...@googlegroups.com
Hi there,

my aim was to reproduce an empty OR query result issue I face, but already fail to build a simple way of presenting it. Hopefully you can show me the right direction.

I have two Models:

@Entity
public class Tag {
   
   
@Id
   
Integer id;
   
   
String name;
   
   
//omitting getters/setters
}
   

@Entity
public class Comment {
   
   
@Id
   
Integer id;
   
   
String author;
   
   
String comment;
   
   
@ManyToMany
   
List<Tag> tags;
   
   
//omitting getters/setters
}




First I save some Tags, then some comments with presaved tags. Problem is, the Tags in the comments never show up (either are not loaded due to lazy load (I doubt that) or not saved at all into the manyToMany table). What could be the cause of this behavior?


Tag apple    = new Tag("apple");
Tag banana    = new Tag("banana");
Ebean.save(Arrays.asList(apple, banana));
       
Comment bob = com("bob", "I like apples.", apple);
Comment mary = com("mary", "Bananas are best.", banana);
Ebean.save(Arrays.asList(bob, mary));

//debug out:
//Tag [id=1, name=apple]
//Tag [id=2, name=banana]
//Comment [id=1, author=bob, comment=I like apples., tags=]
//Comment [id=2, author=mary, comment=Bananas are best., tags=]





Thanks for looking into this issue!
-Quentin

Daryl Stultz

unread,
Aug 5, 2013, 11:19:07 AM8/5/13
to eb...@googlegroups.com
@Entity
public class Tag {
   
   
@Id
   
Integer id;
   
   
String name;
   
   
//omitting getters/setters
}
   

@Entity
public class Comment {
   
   
@Id
   
Integer id;
   
   
String author;
   
   
String comment;
   
   
@ManyToMany
   
List<Tag> tags;
   
   
//omitting getters/setters
}



Try changing your tags annotation to 

@ManyToMany(cascade = CascadeType.PERSIST)

/Daryl

Quentin Volt

unread,
Aug 5, 2013, 2:18:08 PM8/5/13
to eb...@googlegroups.com

Then I get the following exception in line "Ebean.save(Arrays.asList(bob, mary, sam));":

Exception in thread "main" javax.persistence.PersistenceException: ERROR executing DML bindLog[Binding Insert [tag]  set[id=1, name=apple, ]] error[Unique index or primary key violation: "PRIMARY_KEY_1 ON PUBLIC.TAG(ID)"; SQL statement:\n insert into tag (id, name) values (?,?) [23505-168]]
    at com
.avaje.ebeaninternal.server.persist.dml.DmlBeanPersister.execute(DmlBeanPersister.java:116)
    at com
.avaje.ebeaninternal.server.persist.dml.DmlBeanPersister.insert(DmlBeanPersister.java:76)
    at com
.avaje.ebeaninternal.server.persist.DefaultPersistExecute.executeInsertBean(DefaultPersistExecute.java:91)
    at com
.avaje.ebeaninternal.server.core.PersistRequestBean.executeNow(PersistRequestBean.java:500)
    at com
.avaje.ebeaninternal.server.core.PersistRequestBean.executeOrQueue(PersistRequestBean.java:530)
    at com
.avaje.ebeaninternal.server.persist.DefaultPersister.insert(DefaultPersister.java:406)
    at com
.avaje.ebeaninternal.server.persist.DefaultPersister.saveVanillaInsert(DefaultPersister.java:377)
    at com
.avaje.ebeaninternal.server.persist.DefaultPersister.saveVanillaRecurse(DefaultPersister.java:361)
    at com
.avaje.ebeaninternal.server.persist.DefaultPersister.saveRecurse(DefaultPersister.java:308)
    at com
.avaje.ebeaninternal.server.persist.DefaultPersister.saveAssocManyDetails(DefaultPersister.java:923)
    at com
.avaje.ebeaninternal.server.persist.DefaultPersister.saveMany(DefaultPersister.java:798)
    at com
.avaje.ebeaninternal.server.persist.DefaultPersister.saveAssocMany(DefaultPersister.java:711)
    at com
.avaje.ebeaninternal.server.persist.DefaultPersister.insert(DefaultPersister.java:410)
    at com
.avaje.ebeaninternal.server.persist.DefaultPersister.saveVanillaInsert(DefaultPersister.java:377)
    at com
.avaje.ebeaninternal.server.persist.DefaultPersister.saveVanillaRecurse(DefaultPersister.java:361)
    at com
.avaje.ebeaninternal.server.persist.DefaultPersister.saveRecurse(DefaultPersister.java:308)
    at com
.avaje.ebeaninternal.server.persist.DefaultPersister.save(DefaultPersister.java:282)
    at com
.avaje.ebeaninternal.server.core.DefaultServer.save(DefaultServer.java:1820)
    at com
.avaje.ebeaninternal.server.core.DefaultServer.save(DefaultServer.java:1798)
    at com
.avaje.ebean.Ebean.save(Ebean.java:596)
    at com
.avaje.ebean.Ebean.save(Ebean.java:603)
    at mypkg
.Start.main(Start.java:27)
Caused by: org.h2.jdbc.JdbcSQLException: Unique index or primary key violation: "PRIMARY_KEY_1 ON PUBLIC.TAG(ID)"; SQL statement:
insert
into tag (id, name) values (?,?) [23505-168]
    at org
.h2.message.DbException.getJdbcSQLException(DbException.java:329)
    at org
.h2.message.DbException.get(DbException.java:169)
    at org
.h2.message.DbException.get(DbException.java:146)
    at org
.h2.index.BaseIndex.getDuplicateKeyException(BaseIndex.java:81)
    at org
.h2.index.TreeIndex.add(TreeIndex.java:62)
    at org
.h2.table.RegularTable.addRow(RegularTable.java:121)
    at org
.h2.command.dml.Insert.insertRows(Insert.java:124)
    at org
.h2.command.dml.Insert.update(Insert.java:84)
    at org
.h2.command.CommandContainer.update(CommandContainer.java:75)
    at org
.h2.command.Command.executeUpdate(Command.java:230)
    at org
.h2.jdbc.JdbcPreparedStatement.executeUpdateInternal(JdbcPreparedStatement.java:156)
    at org
.h2.jdbc.JdbcPreparedStatement.executeUpdate(JdbcPreparedStatement.java:142)
    at com
.avaje.ebeaninternal.server.lib.sql.ExtendedPreparedStatement.executeUpdate(ExtendedPreparedStatement.java:164)
    at com
.avaje.ebeaninternal.server.type.DataBind.executeUpdate(DataBind.java:74)
    at com
.avaje.ebeaninternal.server.persist.dml.InsertHandler.execute(InsertHandler.java:158)
    at com
.avaje.ebeaninternal.server.persist.dml.DmlBeanPersister.execute(DmlBeanPersister.java:105)
   
... 21 more

Daryl Stultz

unread,
Aug 5, 2013, 2:33:46 PM8/5/13
to eb...@googlegroups.com
On Mon, Aug 5, 2013 at 2:18 PM, Quentin Volt <quenti...@gmail.com> wrote:

Then I get the following exception in line "Ebean.save(Arrays.asList(bob, mary, sam));":

Exception in thread "main" javax.persistence.PersistenceException: ERROR executing DML bindLog[Binding Insert [tag]  set[id=1, name=apple, ]] error[Unique index or primary key violation: "PRIMARY_KEY_1 ON PUBLIC.TAG(ID)"; SQL statement:\n insert into tag (id, name) values (?,?) [23505-168]]

It looks like the ID is not auto-incrementing. Can you post the relevant section of the transaction logs? Also have a look at the DB and see what's in there already before you run the test.

/Daryl

Quentin Volt

unread,
Aug 5, 2013, 3:46:00 PM8/5/13
to eb...@googlegroups.com
I'm using the mem-based h2 db, which should be empty when it starts.

The log entries:
txn[1003], 21:37:35.593, insert into tag (id, name) values (?,?)
txn
[1003], 21:37:35.596, Binding Insert [tag]  set[id=1, name=apple, ]
txn
[1003], 21:37:35.597, Inserted [Tag] [1]
txn
[1003], 21:37:35.597, insert into tag (id, name) values (?,?)
txn
[1003], 21:37:35.597, Binding Insert [tag]  set[id=2, name=banana, ]
txn
[1003], 21:37:35.597, Inserted [Tag] [2]
txn
[1003], 21:37:35.597, insert into tag (id, name) values (?,?)
txn
[1003], 21:37:35.597, Binding Insert [tag]  set[id=3, name=cherry, ]
txn
[1003], 21:37:35.597, Inserted [Tag] [3]
txn
[1003], 21:37:35.597, insert into tag (id, name) values (?,?)
txn
[1003], 21:37:35.597, Binding Insert [tag]  set[id=4, name=banerry, ]
txn
[1003], 21:37:35.597, Inserted [Tag] [4]
txn
[1004], 21:37:35.612, insert into comment (id, author, comment) values (?,?,?)
txn
[1004], 21:37:35.613, Binding Insert [comment]  set[id=1, author=bob, comment=I like apples., ]
txn
[1004], 21:37:35.613, Inserted [Comment] [1]
txn
[1004], 21:37:35.614, insert into tag (id, name) values (?,?)
txn
[1004], 21:37:35.614, Binding Insert [tag]  set[id=1, name=apple, ]
txn
[1004], 21:37:35.628, ERROR executing DML bindLog[Binding Insert [tag]  set[id=1, name=apple, ]] error[Unique index or primary key violation: "PRIMARY_KEY_1 ON PUBLIC.TAG(ID)"; SQL statement:\n insert into tag (id, name) values (?,?) [23505-168]]
txn
[1004], 21:37:35.629, Rollback




...and the console output:
Aug 05, 2013 9:37:34 PM com.avaje.ebeaninternal.server.core.BootupClassPathSearch search
INFO
: Classpath search hits in jars[ebean-2.7.7.jar] pkgs[com.avaje.ebeaninternal.server.bean, mypkg.model, com.avaje.ebean.meta]  searchTime[104]
Aug 05, 2013 9:37:34 PM com.avaje.ebeaninternal.server.lib.sql.DataSourcePool initialise
INFO
: DataSourcePool [h2] autoCommit[false] transIsolation[READ_COMMITTED] min[1] max[25]
Aug 05, 2013 9:37:34 PM com.avaje.ebeaninternal.server.core.DefaultServerFactory setDatabasePlatform
INFO
: DatabasePlatform name:h2 platform:h2
Aug 05, 2013 9:37:34 PM com.avaje.ebeaninternal.server.subclass.SubClassManager$1 run
INFO
: SubClassFactory parent ClassLoader [sun.misc.Launcher$AppClassLoader]
Aug 05, 2013 9:37:35 PM com.avaje.ebeaninternal.server.deploy.BeanDescriptorManager logStatus
INFO
: Entities enhanced[0] subclassed[2]
runScript
executing
1 of 7 SET REFERENTIAL_INTEGRITY FALSE
executing
2 of 7 drop table if exists comment
executing
3 of 7 drop table if exists comment_tag
executing
4 of 7 drop table if exists tag
executing
5 of 7 SET REFERENTIAL_INTEGRITY TRUE
executing
6 of 7 drop sequence if exists comment_seq
executing
7 of 7 drop sequence if exists tag_seq
... end of script
runScript
executing
1 of 7 create table comment ( id                        integer not null, author...
executing
2 of 7 create table tag ( id                        integer not null, name...
executing
3 of 7 create table comment_tag ( comment_id                     integer not null, tag_...
executing
4 of 7 create sequence comment_seq
executing
5 of 7 create sequence tag_seq
executing
6 of 7 alter table comment_tag add constraint fk_comment_tag_comment_01 foreign key (co...
executing
7 of 7 alter table comment_tag add constraint fk_comment_tag_tag_02 foreign key (tag_id...
... end of script
Aug 05, 2013 9:37:35 PM com.avaje.ebeaninternal.server.transaction.log.FileTransactionLoggerWrapper initialiseLogger
INFO
: Transaction logs in: logs
Exception in thread "main" javax.persistence.PersistenceException: ERROR executing DML bindLog[Binding Insert [tag]  set[id=1, name=apple, ]] error[Unique index or primary key violation: "PRIMARY_KEY_1 ON PUBLIC.TAG(ID)"; SQL statement:\n insert into tag (id, name) values (?,?) [23505-168]]

    at com
.avaje.ebeaninternal.server.persist.dml.DmlBeanPersister.execute(DmlBeanPersister.java:116)
    at com
.avaje.ebeaninternal.server.persist.dml.DmlBeanPersister.insert(DmlBeanPersister.java:76)
    at com
.avaje.ebeaninternal.server.persist.DefaultPersistExecute.executeInsertBean(DefaultPersistExecute.java:91)
    at com
.avaje.ebeaninternal.server.core.PersistRequestBean.executeNow(PersistRequestBean.java:500)
    at com
.avaje.ebeaninternal.server.core.PersistRequestBean.executeOrQueue(PersistRequestBean.java:530)
    at com
.avaje.ebeaninternal.server.persist.DefaultPersister.insert(DefaultPersister.java:406)
    at com
.avaje.ebeaninternal.server.persist.DefaultPersister.saveVanillaInsert(DefaultPersister.java:377)
    at com
.avaje.ebeaninternal.server.persist.DefaultPersister.saveVanillaRecurse(DefaultPersister.java:361)
    at com
.avaje.ebeaninternal.server.persist.DefaultPersister.saveRecurse(DefaultPersister.java:308)
    at com
.avaje.ebeaninternal.server.persist.DefaultPersister.saveAssocManyDetails(DefaultPersister.java:923)
    at com
.avaje.ebeaninternal.server.persist.DefaultPersister.saveMany(DefaultPersister.java:798)
    at com
.avaje.ebeaninternal.server.persist.DefaultPersister.saveAssocMany(DefaultPersister.java:711)
    at com
.avaje.ebeaninternal.server.persist.DefaultPersister.insert(DefaultPersister.java:410)
    at com
.avaje.ebeaninternal.server.persist.DefaultPersister.saveVanillaInsert(DefaultPersister.java:377)
    at com
.avaje.ebeaninternal.server.persist.DefaultPersister.saveVanillaRecurse(DefaultPersister.java:361)
    at com
.avaje.ebeaninternal.server.persist.DefaultPersister.saveRecurse(DefaultPersister.java:308)
    at com
.avaje.ebeaninternal.server.persist.DefaultPersister.save(DefaultPersister.java:282)
    at com
.avaje.ebeaninternal.server.core.DefaultServer.save(DefaultServer.java:1820)
    at com
.avaje.ebeaninternal.server.core.DefaultServer.save(DefaultServer.java:1798)
    at com
.avaje.ebean.Ebean.save(Ebean.java:596)
    at com
.avaje.ebean.Ebean.save(Ebean.java:603)
    at mypkg
.Start.main(Start.java:27)
Caused by: org.h2.jdbc.JdbcSQLException: Unique index or primary key violation: "PRIMARY_KEY_1 ON PUBLIC.TAG(ID)"; SQL statement:

insert
into tag (id, name) values (?,?) [23505-168]

Daryl Stultz

unread,
Aug 5, 2013, 4:22:05 PM8/5/13
to eb...@googlegroups.com
On Mon, Aug 5, 2013 at 3:46 PM, Quentin Volt <quenti...@gmail.com> wrote:
I'm using the mem-based h2 db, which should be empty when it starts.

The log entries:
txn[1003], 21:37:35.593, insert into tag (id, name) values (?,?)
txn
[1003], 21:37:35.596, Binding Insert [tag]  set[id=1, name=apple, ]
txn
[1003], 21:37:35.597, Inserted [Tag] [1]
txn
[1003], 21:37:35.597, insert into tag (id, name) values (?,?)
txn
[1003], 21:37:35.597, Binding Insert [tag]  set[id=2, name=banana, ]
txn
[1003], 21:37:35.597, Inserted [Tag] [2]
txn
[1003], 21:37:35.597, insert into tag (id, name) values (?,?)
txn
[1003], 21:37:35.597, Binding Insert [tag]  set[id=3, name=cherry, ]
txn
[1003], 21:37:35.597, Inserted [Tag] [3]
txn
[1003], 21:37:35.597, insert into tag (id, name) values (?,?)
txn
[1003], 21:37:35.597, Binding Insert [tag]  set[id=4, name=banerry, ]
txn
[1003], 21:37:35.597, Inserted [Tag] [4]
txn
[1004], 21:37:35.612, insert into comment (id, author, comment) values (?,?,?)
txn
[1004], 21:37:35.613, Binding Insert [comment]  set[id=1, author=bob, comment=I like apples., ]
txn
[1004], 21:37:35.613, Inserted [Comment] [1]
txn
[1004], 21:37:35.614, insert into tag (id, name) values (?,?)
txn
[1004], 21:37:35.614, Binding Insert [tag]  set[id=1, name=apple, ]
txn
[1004], 21:37:35.628, ERROR executing DML bindLog[Binding Insert [tag]  set[id=1, name=apple, ]] error[Unique index or primary key violation: "PRIMARY_KEY_1 ON PUBLIC.TAG(ID)"; SQL statement:\n insert into tag (id, name) values (?,?) [23505-168]]
txn
[1004], 21:37:35.629, Rollback



Looks like it's trying to insert apple a second time. What happens when you add this before creating "bob":

apple = Ebean.find(Tag.class, apple.getId());
banana = Ebean.find(Tag.class, banana.getId());

/Daryl

Markus Andree

unread,
Aug 5, 2013, 5:58:22 PM8/5/13
to eb...@googlegroups.com
Your log shows that you use subclassing instead of enhancing. Than you should use EBeanServer.createEntityBean(Tag.class) instead of new Tag(), as createEntityBean automatically gets you an instance of the ebean subclass, that is automatically generated for your bean classes. The subclass handles all the magic stuff in the overwritten getters and setters of the class members, and not using it can lead into bad behavior as described here. If you want to use new Tag() instead, you need to enhance your classes after build. When you use maven, you can easily "Enhance the entity beans" as described in the equally named section under http://www.avaje.org/ebean/maven.html

Greets,
Markus

    at org
<span style="color: #660;" class
...

Quentin Volt

unread,
Aug 6, 2013, 2:11:53 AM8/6/13
to eb...@googlegroups.com
Now it's working as intended. CascadeType.PERSIST and the createEntityBean() method solved my issue.

Thank you, Daryl and Markus!

Moving on to the main OR problem I was trying to address :)

 -Quentin
Reply all
Reply to author
Forward
0 new messages