From dev-return-6833-apmail-openjpa-dev-archive=openjpa.apache.org@openjpa.apache.org Sun Nov 18 09:33:04 2007 Return-Path: Delivered-To: apmail-openjpa-dev-archive@www.apache.org Received: (qmail 1106 invoked from network); 18 Nov 2007 09:33:04 -0000 Received: from hermes.apache.org (HELO mail.apache.org) (140.211.11.2) by minotaur.apache.org with SMTP; 18 Nov 2007 09:33:04 -0000 Received: (qmail 2106 invoked by uid 500); 18 Nov 2007 09:32:51 -0000 Delivered-To: apmail-openjpa-dev-archive@openjpa.apache.org Received: (qmail 2076 invoked by uid 500); 18 Nov 2007 09:32:51 -0000 Mailing-List: contact dev-help@openjpa.apache.org; run by ezmlm Precedence: bulk List-Help: List-Unsubscribe: List-Post: List-Id: Reply-To: dev@openjpa.apache.org Delivered-To: mailing list dev@openjpa.apache.org Received: (qmail 2067 invoked by uid 99); 18 Nov 2007 09:32:51 -0000 Received: from athena.apache.org (HELO athena.apache.org) (140.211.11.136) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 18 Nov 2007 01:32:51 -0800 X-ASF-Spam-Status: No, hits=-100.0 required=10.0 tests=ALL_TRUSTED X-Spam-Check-By: apache.org Received: from [140.211.11.4] (HELO brutus.apache.org) (140.211.11.4) by apache.org (qpsmtpd/0.29) with ESMTP; Sun, 18 Nov 2007 09:32:49 +0000 Received: from brutus (localhost [127.0.0.1]) by brutus.apache.org (Postfix) with ESMTP id 052177141EB for ; Sun, 18 Nov 2007 01:32:43 -0800 (PST) Message-ID: <22419299.1195378363010.JavaMail.jira@brutus> Date: Sun, 18 Nov 2007 01:32:43 -0800 (PST) From: =?utf-8?Q?S=C5=82awomir_Wojtasiak_=28JIRA=29?= To: dev@openjpa.apache.org Subject: [jira] Updated: (OPENJPA-444) Unnecessary updates during flush operation. In-Reply-To: <13951456.1195378123309.JavaMail.jira@brutus> MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: quoted-printable X-Virus-Checked: Checked by ClamAV on apache.org [ https://issues.apache.org/jira/browse/OPENJPA-444?page=3Dcom.atlassi= an.jira.plugin.system.issuetabpanels:all-tabpanel ] S=C5=82awomir Wojtasiak updated OPENJPA-444: --------------------------------------- Description:=20 OpenJPA performs unnecessary updates during flush operation. For example: When we are trying to persist versioned entity with collection of other ent= ities: |Article|1-------------*|Quantity| ( Relation owner. ) ************ CODE ************* EntityManagerFactory factory =3D Persistence.createEntityManagerFactory( "t= estjpa", System.getProperties() ); EntityManager em =3D factory.createEntityManager(); em.getTransaction().begin(); Article a =3D new Article(); a.setName( "atricle" ); =09=09 Quantity q =3D new Quantity(); q.setName( "quantity" ); q.setArticle( a ); =09=09 a.getQuantities().add( q ); =09=09 em.persist( a ); em.flush(); em.flush(); ************* END OF CODE ************ Following queries are generated after first flush operation: SELECT SEQUENCE_VALUE FROM OPENJPA_SEQUENCE_TABLE WHERE ID =3D ? FOR UPDATE= [params=3D(int) 0] UPDATE OPENJPA_SEQUENCE_TABLE SET SEQUENCE_VALUE =3D ? WHERE ID =3D ? AND S= EQUENCE_VALUE =3D ? [params=3D(long) 2651, (int) 0, (long) 2601] SELECT SEQUENCE_VALUE FROM OPENJPA_SEQUENCE_TABLE WHERE ID =3D ? FOR UPDATE= [params=3D(int) 0] UPDATE OPENJPA_SEQUENCE_TABLE SET SEQUENCE_VALUE =3D ? WHERE ID =3D ? AND S= EQUENCE_VALUE =3D ? [params=3D(long) 2701, (int) 0, (long) 2651] INSERT INTO Article (id, name, version) VALUES (?, ?, ?) [params=3D(long) 2= 601, (String) atricle, (int) 1] INSERT INTO Quantity (id, name, version, article_id) VALUES (?, ?, ?, ?) [p= arams=3D(long) 2651, (String) quantity, (int) 1, (long) 2601] Everything looks ok but after next flush we will get version update: UPDATE Article SET version =3D ? WHERE id =3D ? AND version =3D ? [params= =3D(int) 2, (long) 2601, (int) 1] I am not completely sure that this analysis is correct, but I hope it helps= anyway: During persist operation SaveFieldManager sets collection of quantities as = unloaded and unsaved field (Because this field is mutable). During next flu= sh, StateManager checks which fields are dirty by comparing its values to t= hose stored by SaveFieldManager. Method dirtyCheck() of the StateManager is= responsible for that. (It's necessary taking into consideration fact that = I do not use OpenJPA enhancer with JDK 5.0). SaveFieldManager always retur= ns false from its isFieldEqual() method because this collection (Collection= of quantities) is treated as unsaved ( Comment from OpenJPA code: if the = field is not available, assume that it has changed) so StateManager sets it= as dirty and clears its flush bit. Then AbstractUpdateManager try to add U= PDATE_ACTION for this dirty collection, but with no effect because this fie= ld is not set as updatable and insertable ( I think so. ). In next step Abs= tractUpdateManager adds UPDATE_ACTION for version field because StateManage= r is marked as dirty. It causes unnecessary update of entity version field = because nothing changed in the database.=20 I didn't check how it works with field tracking. ******************** EXAMPLE ENTITIES ****************** @Entity public class Article { =09private long id; =09private long version; =09private String name; =09private Set quantities =3D new HashSet(); =09@Id =09@GeneratedValue( strategy =3D GenerationType.SEQUENCE ) =09public long getId() { =09=09return id; =09} =09public void setId( long id ) { =09=09this.id =3D id; =09} =09@Version =09public long getVersion() { =09=09return version; =09} =09public void setVersion( long version ) { =09=09this.version =3D version; =09} =09@Basic =09public String getName() { =09=09return name; =09} =09public void setName( String name ) { =09=09this.name =3D name; =09} =09@OneToMany( mappedBy =3D "article", cascade =3D { CascadeType.MERGE, Cas= cadeType.PERSIST }, fetch =3D FetchType.LAZY ) =09public Set getQuantities() { =09=09return quantities; =09} =09public void setQuantities( Set quantities ) { =09=09this.quantities =3D quantities; =09} } @Entity public class Quantity { =09private long id; =09private long version; =09private String name; =09private Article article; =09@Id =09@GeneratedValue( strategy =3D GenerationType.SEQUENCE ) =09public long getId() { =09=09return id; =09} =09public void setId( long id ) { =09=09this.id =3D id; =09} =09@Version =09public long getVersion() { =09=09return version; =09} =09public void setVersion( long version ) { =09=09this.version =3D version; =09} =09@Basic =09public String getName() { =09=09return name; =09} =09public void setName( String name ) { =09=09this.name =3D name; =09} =09@ManyToOne( optional =3D false, cascade =3D { CascadeType.PERSIST, Casca= deType.MERGE }, fetch =3D FetchType.LAZY ) =09public Article getArticle() { =09=09return article; =09} =09public void setArticle( Article article ) { =09=09this.article =3D article; =09} } was: OpenJPA performs unnecessary updates during flush operation. For example: When we are trying to persist versioned entity with collection of other ent= ities: |Article|1-------------*|Quantity| ( Relation owner. ) ************ CODE ************* EntityManagerFactory factory =3D Persistence.createEntityManagerFactory( "t= estjpa", System.getProperties() ); EntityManager em =3D factory.createEntityManager(); em.getTransaction().begin(); Article a =3D new Article(); a.setName( "atricle" ); =09=09 Quantity q =3D new Quantity(); q.setName( "quantity" ); q.setArticle( a ); =09=09 a.getQuantities().add( q ); =09=09 em.persist( a ); em.flush(); em.flush(); ************* END OF CODE ************ Following queries are generated after first flush operation: SELECT SEQUENCE_VALUE FROM OPENJPA_SEQUENCE_TABLE WHERE ID =3D ? FOR UPDATE= [params=3D(int) 0] UPDATE OPENJPA_SEQUENCE_TABLE SET SEQUENCE_VALUE =3D ? WHERE ID =3D ? AND S= EQUENCE_VALUE =3D ? [params=3D(long) 2651, (int) 0, (long) 2601] SELECT SEQUENCE_VALUE FROM OPENJPA_SEQUENCE_TABLE WHERE ID =3D ? FOR UPDATE= [params=3D(int) 0] UPDATE OPENJPA_SEQUENCE_TABLE SET SEQUENCE_VALUE =3D ? WHERE ID =3D ? AND S= EQUENCE_VALUE =3D ? [params=3D(long) 2701, (int) 0, (long) 2651] INSERT INTO Article (id, name, version) VALUES (?, ?, ?) [params=3D(long) 2= 601, (String) atricle, (int) 1] INSERT INTO Quantity (id, name, version, article_id) VALUES (?, ?, ?, ?) [p= arams=3D(long) 2651, (String) quantity, (int) 1, (long) 2601] Everything looks ok but after next flush we will get version update: UPDATE Article SET version =3D ? WHERE id =3D ? AND version =3D ? [params= =3D(int) 2, (long) 2601, (int) 1] I am not completely sure that this analysis is correct, but I hope it helps= anyway: During persist operation SaveFieldManager sets collection of quantities as = unloaded and unsaved field (Because this field is mutable). During next flu= sh, StateManager checks which fields are dirty by comparing its values to t= hose stored by SaveFieldManager. Method dirtyCheck() of the StateManager is= responsible for that. (It's necessary taking into consideration fact that = I do not use OpenJPA enhancer with JDK 5.0). SaveFieldManager always retur= ns false from its isFieldEqual() method because this collection (Collection= of quantities) is treated as unsaved ( Comment from OpenJPA code: if the = field is not available, assume that it has changed) so StateManager sets it= as dirty and clears its flush bit. Then AbstractUpdateManager try to add U= PDATE_ACTION for this dirty collection, but with no effect because this fie= ld is not set as updatable and insertable ( I think so. ). In next step Abs= tractUpdateManager adds UPDATE_ACTION for version field because StateManage= r is marked as dirty. It causes unnecessary update of entity version field = because nothing changed in the database.=20 I didn't check how it works with field tracking. > Unnecessary updates during flush operation. > ------------------------------------------- > > Key: OPENJPA-444 > URL: https://issues.apache.org/jira/browse/OPENJPA-444 > Project: OpenJPA > Issue Type: Bug > Components: kernel > Affects Versions: 1.0.1 > Environment: OpenJPA without field tracking. (JDK 5.0 ) > Reporter: S=C5=82awomir Wojtasiak > > OpenJPA performs unnecessary updates during flush operation. For example: > When we are trying to persist versioned entity with collection of other e= ntities: > |Article|1-------------*|Quantity| ( Relation owner. ) > ************ CODE ************* > EntityManagerFactory factory =3D Persistence.createEntityManagerFactory( = "testjpa", System.getProperties() ); > EntityManager em =3D factory.createEntityManager(); > em.getTransaction().begin(); > Article a =3D new Article(); > a.setName( "atricle" ); > =09=09 > Quantity q =3D new Quantity(); > q.setName( "quantity" ); > q.setArticle( a ); > =09=09 > a.getQuantities().add( q ); > =09=09 > em.persist( a ); > em.flush(); > em.flush(); > ************* END OF CODE ************ > Following queries are generated after first flush operation: > SELECT SEQUENCE_VALUE FROM OPENJPA_SEQUENCE_TABLE WHERE ID =3D ? FOR UPDA= TE [params=3D(int) 0] > UPDATE OPENJPA_SEQUENCE_TABLE SET SEQUENCE_VALUE =3D ? WHERE ID =3D ? AND= SEQUENCE_VALUE =3D ? [params=3D(long) 2651, (int) 0, (long) 2601] > SELECT SEQUENCE_VALUE FROM OPENJPA_SEQUENCE_TABLE WHERE ID =3D ? FOR UPDA= TE [params=3D(int) 0] > UPDATE OPENJPA_SEQUENCE_TABLE SET SEQUENCE_VALUE =3D ? WHERE ID =3D ? AND= SEQUENCE_VALUE =3D ? [params=3D(long) 2701, (int) 0, (long) 2651] > INSERT INTO Article (id, name, version) VALUES (?, ?, ?) [params=3D(long)= 2601, (String) atricle, (int) 1] > INSERT INTO Quantity (id, name, version, article_id) VALUES (?, ?, ?, ?) = [params=3D(long) 2651, (String) quantity, (int) 1, (long) 2601] > Everything looks ok but after next flush we will get version update: > UPDATE Article SET version =3D ? WHERE id =3D ? AND version =3D ? [params= =3D(int) 2, (long) 2601, (int) 1] > I am not completely sure that this analysis is correct, but I hope it hel= ps anyway: > During persist operation SaveFieldManager sets collection of quantities a= s unloaded and unsaved field (Because this field is mutable). During next f= lush, StateManager checks which fields are dirty by comparing its values to= those stored by SaveFieldManager. Method dirtyCheck() of the StateManager = is responsible for that. (It's necessary taking into consideration fact tha= t I do not use OpenJPA enhancer with JDK 5.0). SaveFieldManager always ret= urns false from its isFieldEqual() method because this collection (Collecti= on of quantities) is treated as unsaved ( Comment from OpenJPA code: if th= e field is not available, assume that it has changed) so StateManager sets = it as dirty and clears its flush bit. Then AbstractUpdateManager try to add= UPDATE_ACTION for this dirty collection, but with no effect because this f= ield is not set as updatable and insertable ( I think so. ). In next step A= bstractUpdateManager adds UPDATE_ACTION for version field because StateMana= ger is marked as dirty. It causes unnecessary update of entity version fiel= d because nothing changed in the database.=20 > I didn't check how it works with field tracking. > ******************** EXAMPLE ENTITIES ****************** > @Entity > public class Article { > =09private long id; > =09private long version; > =09private String name; > =09private Set quantities =3D new HashSet(); > =09@Id > =09@GeneratedValue( strategy =3D GenerationType.SEQUENCE ) > =09public long getId() { > =09=09return id; > =09} > =09public void setId( long id ) { > =09=09this.id =3D id; > =09} > =09@Version > =09public long getVersion() { > =09=09return version; > =09} > =09public void setVersion( long version ) { > =09=09this.version =3D version; > =09} > =09@Basic > =09public String getName() { > =09=09return name; > =09} > =09public void setName( String name ) { > =09=09this.name =3D name; > =09} > =09@OneToMany( mappedBy =3D "article", cascade =3D { CascadeType.MERGE, C= ascadeType.PERSIST }, fetch =3D FetchType.LAZY ) > =09public Set getQuantities() { > =09=09return quantities; > =09} > =09public void setQuantities( Set quantities ) { > =09=09this.quantities =3D quantities; > =09} > } > @Entity > public class Quantity { > =09private long id; > =09private long version; > =09private String name; > =09private Article article; > =09@Id > =09@GeneratedValue( strategy =3D GenerationType.SEQUENCE ) > =09public long getId() { > =09=09return id; > =09} > =09public void setId( long id ) { > =09=09this.id =3D id; > =09} > =09@Version > =09public long getVersion() { > =09=09return version; > =09} > =09public void setVersion( long version ) { > =09=09this.version =3D version; > =09} > =09@Basic > =09public String getName() { > =09=09return name; > =09} > =09public void setName( String name ) { > =09=09this.name =3D name; > =09} > =09@ManyToOne( optional =3D false, cascade =3D { CascadeType.PERSIST, Cas= cadeType.MERGE }, fetch =3D FetchType.LAZY ) > =09public Article getArticle() { > =09=09return article; > =09} > =09public void setArticle( Article article ) { > =09=09this.article =3D article; > =09} > } --=20 This message is automatically generated by JIRA. - You can reply to this email to add a comment to the issue online.