When is the @Version field of a 'parent' entity updated?
Hi, I have classes mapped like this: class Parent { @Id int parentId; @Version int version; @OneToMany(...) ListChild children; } class Child { @Id int childId; ... // no relationship to parent, its uni-directional } The foreign key is on the CHILD table, but in JPA parlance the 'owner' of the relationship is the Parent, since it is uni-directional. It is kind of implied by this that this is a relationship by composition; the Child is part of the Parent and does not exist independently of it. We noticed that when a new Child is added to a Parent, the version stamp on the parent is bumped by one. From a database point of view this seems incorrect, since only the CHILD table is modified, and PARENT does not need to be touched. From a OO point of view, this seems correct, since the list on the Parent was updated, so Parent has changed. http://en.wikibooks.org/wiki/Java_Persistence/Locking#Cascaded_Locking Sheds some light on the issue: Locking objects is different than locking rows in the database. An object can be more complex than a simple row; an object can span multiple tables, have inheritance, have relationships, and have dependent objects. So determining when an object has *changed* and needs to update its' version can be more difficult than determining when a row has changed. So my question is: In what circumstances would the Parent version be bumped by one? Does it happen on all relationships, or only to the side of a relationship considered to be the 'owner'. For example, If I put a @ManyToOne link back from Child to Parent, so that Child is now the 'owner' of the relationship, and holds the foreign key, it is kind of implied that this is a relationship by aggregation and the Child is independent. Would the Parent version still get bumped by one in this case? Is there an option in OpenJPA to turn off bumping of the parent version? Thanks for your help. Rupert
behavior change from 2.1.0 to 2.2.0 on persist
Hey, we recently switched to 2.2.0 (cant go higher because we use Java8) and we found a change in behavior. Asumme we created a new Entity which looks like this: Person.java -- int oid String name CustomerType adress we created the object like so: Person p = new Person(); p.setName(foo); CustomerType ct = new CustomerType(); ct.setOid(1); // THIS OID already exists and we want to map the existant object to Person p.setCustomerType(ct); persist(p); = In 2.1.0 OpemJPA knew that there is a CustomerType in the DB with this oid and loads it automaticly and the child object is managed. With 2.2.0 this is no longer the case and we get a Unmanaged bla bla bla Exception. We relied on that behavior heavily and the rewrite is a tough for all areas. Is there some kind of config setting where i can set the old behavior. Or was this old behavior a bug? ;-) Thanks for hints. Marc
Re: When is the @Version field of a 'parent' entity updated?
@Version is used to support optimistic locking semantics at the object level and bear no implication to db row or ownership. In what circumstances would the Parent version be bumped by one? When an entity is changed and needs to be updated back to the database row, the version field must be incremented to avoid updating row that may have been updated by another client or catch the case where another client already had the row updated. Is there an option in OpenJPA to turn off bumping of the parent version? You can disable optimistic lock versioning by removing @Version from the version field. However you are risking overwriting object content in the db unless your application can guarantee this scenario would not happen. Albert. On Mon, Jun 2, 2014 at 3:52 AM, Rupert Smith rupertlssm...@googlemail.com wrote: Hi, I have classes mapped like this: class Parent { @Id int parentId; @Version int version; @OneToMany(...) ListChild children; } class Child { @Id int childId; ... // no relationship to parent, its uni-directional } The foreign key is on the CHILD table, but in JPA parlance the 'owner' of the relationship is the Parent, since it is uni-directional. It is kind of implied by this that this is a relationship by composition; the Child is part of the Parent and does not exist independently of it. We noticed that when a new Child is added to a Parent, the version stamp on the parent is bumped by one. From a database point of view this seems incorrect, since only the CHILD table is modified, and PARENT does not need to be touched. From a OO point of view, this seems correct, since the list on the Parent was updated, so Parent has changed. http://en.wikibooks.org/wiki/Java_Persistence/Locking#Cascaded_Locking Sheds some light on the issue: Locking objects is different than locking rows in the database. An object can be more complex than a simple row; an object can span multiple tables, have inheritance, have relationships, and have dependent objects. So determining when an object has *changed* and needs to update its' version can be more difficult than determining when a row has changed. So my question is: In what circumstances would the Parent version be bumped by one? Does it happen on all relationships, or only to the side of a relationship considered to be the 'owner'. For example, If I put a @ManyToOne link back from Child to Parent, so that Child is now the 'owner' of the relationship, and holds the foreign key, it is kind of implied that this is a relationship by aggregation and the Child is independent. Would the Parent version still get bumped by one in this case? Is there an option in OpenJPA to turn off bumping of the parent version? Thanks for your help. Rupert -- Albert Lee.
Re: behavior change from 2.1.0 to 2.2.0 on persist
Hi Marc, Sorry for the troubles. Technically, it looks like you were lucky and coding to a bug in the OpenJPA code. Since you just created this CustomerType, we have to assume that it's unmanaged. And, we can't automatically cascade the persist operation to this unmanaged entity. And, in your particular case, we wouldn't want to persist this entity since it already exists. Just to be clear, you don't want this CustomerType to be persisted, right? You are just creating this to satisfy the relationship from Person, right? A couple of ideas come to mind... 1) Can you do an em.find() operation on your CustomerType? I realize this is an extra SQL, but then this CustomerType would be managed and satisfy the requirement. 2) Have you tried using em.merge(p) instead of em.persist(p)? The merge should do either the update or insert based on the state of the object. When we get to the CustomerType, we might have to do the extra SQL to determine if it exists already, but then we should be okay. This JIRA [1] from the 2.2.0 Release Notes [2] makes me think this might work... Maybe somebody else has some ideas on how to get around this scenario. [1] https://issues.apache.org/jira/browse/OPENJPA-1896 [2] http://openjpa.apache.org/builds/2.2.0/apache-openjpa/RELEASE-NOTES.html On Mon, Jun 2, 2014 at 7:48 AM, Marc Logemann marc.logem...@gmail.com wrote: Hey, we recently switched to 2.2.0 (cant go higher because we use Java8) and we found a change in behavior. Asumme we created a new Entity which looks like this: Person.java -- int oid String name CustomerType adress we created the object like so: Person p = new Person(); p.setName(foo); CustomerType ct = new CustomerType(); ct.setOid(1); // THIS OID already exists and we want to map the existant object to Person p.setCustomerType(ct); persist(p); = In 2.1.0 OpemJPA knew that there is a CustomerType in the DB with this oid and loads it automaticly and the child object is managed. With 2.2.0 this is no longer the case and we get a Unmanaged bla bla bla Exception. We relied on that behavior heavily and the rewrite is a tough for all areas. Is there some kind of config setting where i can set the old behavior. Or was this old behavior a bug? ;-) Thanks for hints. Marc
AW: behavior change from 2.1.0 to 2.2.0 on persist
Hello, We solved this by using the getReference() method. Something like Person p = new Person(); p.setName(foo); p.setCustomerType(em.getReference(CustomerType.class, 1); persist(p); John -Ursprüngliche Nachricht- Von: Kevin Sutter [mailto:kwsut...@gmail.com] Gesendet: Montag, 2. Juni 2014 16:11 An: users@openjpa.apache.org Betreff: Re: behavior change from 2.1.0 to 2.2.0 on persist Hi Marc, Sorry for the troubles. Technically, it looks like you were lucky and coding to a bug in the OpenJPA code. Since you just created this CustomerType, we have to assume that it's unmanaged. And, we can't automatically cascade the persist operation to this unmanaged entity. And, in your particular case, we wouldn't want to persist this entity since it already exists. Just to be clear, you don't want this CustomerType to be persisted, right? You are just creating this to satisfy the relationship from Person, right? A couple of ideas come to mind... 1) Can you do an em.find() operation on your CustomerType? I realize this is an extra SQL, but then this CustomerType would be managed and satisfy the requirement. 2) Have you tried using em.merge(p) instead of em.persist(p)? The merge should do either the update or insert based on the state of the object. When we get to the CustomerType, we might have to do the extra SQL to determine if it exists already, but then we should be okay. This JIRA [1] from the 2.2.0 Release Notes [2] makes me think this might work... Maybe somebody else has some ideas on how to get around this scenario. [1] https://issues.apache.org/jira/browse/OPENJPA-1896 [2] http://openjpa.apache.org/builds/2.2.0/apache-openjpa/RELEASE-NOTES.html On Mon, Jun 2, 2014 at 7:48 AM, Marc Logemann marc.logem...@gmail.com wrote: Hey, we recently switched to 2.2.0 (cant go higher because we use Java8) and we found a change in behavior. Asumme we created a new Entity which looks like this: Person.java -- int oid String name CustomerType adress we created the object like so: Person p = new Person(); p.setName(foo); CustomerType ct = new CustomerType(); ct.setOid(1); // THIS OID already exists and we want to map the existant object to Person p.setCustomerType(ct); persist(p); = In 2.1.0 OpemJPA knew that there is a CustomerType in the DB with this oid and loads it automaticly and the child object is managed. With 2.2.0 this is no longer the case and we get a Unmanaged bla bla bla Exception. We relied on that behavior heavily and the rewrite is a tough for all areas. Is there some kind of config setting where i can set the old behavior. Or was this old behavior a bug? ;-) Thanks for hints. Marc
Re: behavior change from 2.1.0 to 2.2.0 on persist
Kevin, thanks for fast feedback. To your questions: 1) of course we could do the em.find() and do it the way it should be done ;-) 2) no, we have not tried using em.merge(), this would be an option we could check out. And yes. WE dont want to persist the CustomerType since its already there. We just want to create the relationship. Thanks again. And now we will happily wait for Java8 Support in your bytecode enhancer so that we could upgrade to latest Version of OpenJPA instead of being stuck to 2.2.0 ;-) Marc 2014-06-02 16:11 GMT+02:00 Kevin Sutter kwsut...@gmail.com: Hi Marc, Sorry for the troubles. Technically, it looks like you were lucky and coding to a bug in the OpenJPA code. Since you just created this CustomerType, we have to assume that it's unmanaged. And, we can't automatically cascade the persist operation to this unmanaged entity. And, in your particular case, we wouldn't want to persist this entity since it already exists. Just to be clear, you don't want this CustomerType to be persisted, right? You are just creating this to satisfy the relationship from Person, right? A couple of ideas come to mind... 1) Can you do an em.find() operation on your CustomerType? I realize this is an extra SQL, but then this CustomerType would be managed and satisfy the requirement. 2) Have you tried using em.merge(p) instead of em.persist(p)? The merge should do either the update or insert based on the state of the object. When we get to the CustomerType, we might have to do the extra SQL to determine if it exists already, but then we should be okay. This JIRA [1] from the 2.2.0 Release Notes [2] makes me think this might work... Maybe somebody else has some ideas on how to get around this scenario. [1] https://issues.apache.org/jira/browse/OPENJPA-1896 [2] http://openjpa.apache.org/builds/2.2.0/apache-openjpa/RELEASE-NOTES.html On Mon, Jun 2, 2014 at 7:48 AM, Marc Logemann marc.logem...@gmail.com wrote: Hey, we recently switched to 2.2.0 (cant go higher because we use Java8) and we found a change in behavior. Asumme we created a new Entity which looks like this: Person.java -- int oid String name CustomerType adress we created the object like so: Person p = new Person(); p.setName(foo); CustomerType ct = new CustomerType(); ct.setOid(1); // THIS OID already exists and we want to map the existant object to Person p.setCustomerType(ct); persist(p); = In 2.1.0 OpemJPA knew that there is a CustomerType in the DB with this oid and loads it automaticly and the child object is managed. With 2.2.0 this is no longer the case and we get a Unmanaged bla bla bla Exception. We relied on that behavior heavily and the rewrite is a tough for all areas. Is there some kind of config setting where i can set the old behavior. Or was this old behavior a bug? ;-) Thanks for hints. Marc
Re: behavior change from 2.1.0 to 2.2.0 on persist
Marc -- I'm thinking that there was a change in cascade persist behavior that you might be running into. http://openjpa.apache.org/builds/2.2.2/apache-openjpa/docs/jpa_2.2.html#jpa_2.2_cascadePersist On Mon, Jun 2, 2014 at 9:53 AM, Marc Logemann marc.logem...@gmail.com wrote: Kevin, thanks for fast feedback. To your questions: 1) of course we could do the em.find() and do it the way it should be done ;-) 2) no, we have not tried using em.merge(), this would be an option we could check out. And yes. WE dont want to persist the CustomerType since its already there. We just want to create the relationship. Thanks again. And now we will happily wait for Java8 Support in your bytecode enhancer so that we could upgrade to latest Version of OpenJPA instead of being stuck to 2.2.0 ;-) Marc 2014-06-02 16:11 GMT+02:00 Kevin Sutter kwsut...@gmail.com: Hi Marc, Sorry for the troubles. Technically, it looks like you were lucky and coding to a bug in the OpenJPA code. Since you just created this CustomerType, we have to assume that it's unmanaged. And, we can't automatically cascade the persist operation to this unmanaged entity. And, in your particular case, we wouldn't want to persist this entity since it already exists. Just to be clear, you don't want this CustomerType to be persisted, right? You are just creating this to satisfy the relationship from Person, right? A couple of ideas come to mind... 1) Can you do an em.find() operation on your CustomerType? I realize this is an extra SQL, but then this CustomerType would be managed and satisfy the requirement. 2) Have you tried using em.merge(p) instead of em.persist(p)? The merge should do either the update or insert based on the state of the object. When we get to the CustomerType, we might have to do the extra SQL to determine if it exists already, but then we should be okay. This JIRA [1] from the 2.2.0 Release Notes [2] makes me think this might work... Maybe somebody else has some ideas on how to get around this scenario. [1] https://issues.apache.org/jira/browse/OPENJPA-1896 [2] http://openjpa.apache.org/builds/2.2.0/apache-openjpa/RELEASE-NOTES.html On Mon, Jun 2, 2014 at 7:48 AM, Marc Logemann marc.logem...@gmail.com wrote: Hey, we recently switched to 2.2.0 (cant go higher because we use Java8) and we found a change in behavior. Asumme we created a new Entity which looks like this: Person.java -- int oid String name CustomerType adress we created the object like so: Person p = new Person(); p.setName(foo); CustomerType ct = new CustomerType(); ct.setOid(1); // THIS OID already exists and we want to map the existant object to Person p.setCustomerType(ct); persist(p); = In 2.1.0 OpemJPA knew that there is a CustomerType in the DB with this oid and loads it automaticly and the child object is managed. With 2.2.0 this is no longer the case and we get a Unmanaged bla bla bla Exception. We relied on that behavior heavily and the rewrite is a tough for all areas. Is there some kind of config setting where i can set the old behavior. Or was this old behavior a bug? ;-) Thanks for hints. Marc -- *Rick Curtis*