@OneToOne relation causes insert instead of update in SQL

1,220 views
Skip to first unread message

Jens Tinglev

unread,
Jun 17, 2013, 8:36:18 AM6/17/13
to eb...@googlegroups.com
I'm developing a Play 2.1 webapp (using EBean as the ORM), and I'm having some trouble with my models one-to-one-relationships.

I have two models. A person:

@Entity
@Table(name="PERSON")
public class Person extends Model {


@Id
@GeneratedValue
public long id;


@Version
public long version;


@OneToOne(mappedBy="owner",
   cascade
=CascadeType.ALL,
   optional 
= true)
@Valid
public MiscInformation miscInformation;


...


}


And a MiscInformation:

@Entity
@Table(name="MISC_INFORMATION")
public class MiscInformation extends Model {


@Id
@GeneratedValue
public long id;


@OneToOne(optional = false)
@JoinColumn(name = "person_id", unique = true)
public Person owner;


@Version
public long version;


...


}

And this is the code that does the save/update of the Person:

Person foundPerson = getPersonFromDatabase(p);
if(foundPerson != null) {
  p
.update(p.id);
} else {
  p
.save();
}

When I create a new Person, foundPerson in this code snippet becomes null (since the id is negative) and everything works fine. Logs from EBean shows that inserts are performed all around.

When I use a view in Play to do a bindFromRequest into a Person and run the code to save/update again, an existing Person is found in the database and the p.update(p.id) is run.
The EBean SQL logs show that the Person is correctly updated, and has it's version increased and everything. The MiscInformation is however not being updated, but instead inserted!

[debug] c.j.b.PreparedStatementHandle - insert into MISC_INFORMATION (id, gender, percent_research, docent_qualification, docent_degree_year, version, person_id) values(1,'male','80',true,'1995',1,1)

Which causes:

javax.persistence.PersistenceException: ERROR executing DML bindLog[] error[ERROR: duplicate key value violates unique constraint "pk_misc_information"\n   Detail: Key (id)=(1) already exists.]

I also have several models marked with @OneToMany in the Person-class, which works fine when performing the p.update(..).

Any ideas?

Thanks!

edge

unread,
Jun 17, 2013, 9:17:36 AM6/17/13
to eb...@googlegroups.com
I don't see anything wrong with the mapping and can't tell if its an ebean or play problem. 
Did you try using the entity you retrieve from the DB instead?
Person foundPerson = getPersonFromDatabase(p);
if(foundPerson != null) {

  
foundPerson.update(foundPerson.id);
} else {
  p
.save();

Jens Tinglev

unread,
Jun 17, 2013, 9:25:29 AM6/17/13
to eb...@googlegroups.com
If I use the Person retrieved from the database I guess all the changes made to the Person retrieved from the webform (the parameter p) will be lost. I'm just saving/updating the existing record in the database with data I just fetched from that same record.

I've also posted this error on the Google group for Play framework, but I'm suspecting that this is in fact related to how EBean handles this type of relation. If I use the syntax EBean.update(p), I still get the same error.

edge

unread,
Jun 17, 2013, 9:33:01 AM6/17/13
to eb...@googlegroups.com
I meant just as a test to see if it works - you'll probably need to change some value to ensure the entity is dirty 
I think we have similar entities with OneToOne mappings working in our tests but I'll take a look a little later and get back to you

Jens Tinglev

unread,
Jun 17, 2013, 9:42:00 AM6/17/13
to eb...@googlegroups.com
Alright!

I changed the update routine to this:

foundPerson.city = "No city";
foundPerson.miscInformation.gender = "Something special";
foundPerson.update(foundPerson.id);

Which was successful, with the following SQL debug prints:

[debug] c.j.b.PreparedStatementHandle - update PERSON set city='No city', version=4 where id=1 and version=3
[debug] c.j.b.PreparedStatementHandle - update MISC_INFORMATION set gender='Something special', version=3 where id=1 and version=2

So that obviously seems to work as intended.

edge

unread,
Jun 17, 2013, 9:50:49 AM6/17/13
to eb...@googlegroups.com
hmmm looks like a play issue I think as the mappings work. Somehow the state of the bean is inconsistent in your original code after saving. Try searching the play forum as the problem seems vaguely familiar. 

Jens Tinglev

unread,
Jun 18, 2013, 2:33:18 AM6/18/13
to eb...@googlegroups.com
Thanks for your input. I'm beginning to think that this has something to do with the Person model being stateless due to it's binding from a webform. ORM + stateless entities is a bad idea obviously.

The only problem with this theory is why the update of Person and the @OneToMany-relations seem to work?

Emiliano Anichini

unread,
Aug 8, 2014, 5:26:31 AM8/8/14
to eb...@googlegroups.com
Hi.
Same issue here. I have an Article with a OneToOne relation with Metadata. The debug log is this:

[debug] c.j.b.PreparedStatementHandle - update article set ...
[debug] c.j.b.PreparedStatementHandle - insert into metadata (id, article_id) values (2,2)
[error] play - Cannot invoke the action, eventually got an error: javax.persistence.PersistenceException: ERROR executing DML bindLog[] error[Duplicate entry '2' for key 'PRIMARY']

In the play view I must use, as workaround, a hidden field with articleForm("metadata.id") because despite the article.metadata data is retrieved correctly in the view (first access), it disappear (only the id!) on controller side on save form, so the workaround.

I use play-java_2.10-2.2.2 with play-java-ebean_2.10-2.2.2 as ORM.


thank you.


Rob Bygrave

unread,
Aug 8, 2014, 5:48:28 AM8/8/14
to ebean@googlegroups
Ideally you would create a test case that shows your issue.

>>
Person foundPerson = getPersonFromDatabase(p);
if(foundPerson != null) {
  p
.update(p.id);
} else {
  p
.save();
}
<<

This code does not make sense to me in that you fetch foundPerson but then save/update p -  it is not clear what is going on there.

Unfortunately the Play guys didn't know what they were doing with that update(id) method. It doesn't really make any sense ... save() does both an insert or an update based on the bean state.  


Cheers, Rob.



--

---
You received this message because you are subscribed to the Google Groups "Ebean ORM" group.
To unsubscribe from this group and stop receiving emails from it, send an email to ebean+un...@googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Emiliano Anichini

unread,
Aug 22, 2014, 4:13:49 AM8/22/14
to eb...@googlegroups.com
I've made a "project" here about OneToOne relationship.

It seems even the save doesn't work at all (but OneToMany does).



thanks for the help.


(I've posted the same question here with no answer, for now)
Reply all
Reply to author
Forward
0 new messages