You are viewing a plain text version of this content. The canonical link for it is here.
Posted to users@openjpa.apache.org by Alain Brazeau <ab...@rogers.com> on 2014/03/23 00:53:32 UTC

Unecessary database update?

My application has the following bidirectional one-to-many association:

@Entity
@Table(name="TB_CUSTOMERS")
public class Customer {

    @OneToMany(mappedBy="customer", cascade={CascadeType.PERSIST,
CascadeType.REMOVE})
    @OrderBy("createdDate DESC")
    private List<Order> orders = new ArrayList<Order>();

...

}

@Entity
@Table(name="TB_ORDERS")
public class Order {

    @ManyToOne
    @JoinColumn(name="CUSTOMER_ID")
    private Customer customer;

...

}

I recently noticed that when a new Order object is added to a Customer
object's Order List, the underlying Customer database table record gets
updated, even though the Customer object was not modified.  This is
especially problematic since I have a database trigger defined on the
Customer table that inserts the old version of a record in a Customer
history table for auditing purposes whenever an update occurs.        

I am currently using OpenJPA version 2.0.1.  I have tried upgrading to
version 2.2.2, but still have the same problem.  If I use Hibernate instead
of OpenJPA as the JPA implementation, the Customer database table does NOT
get updated.

Based on my understanding of JPA, the Customer record should not get updated
unless LockModeType.OPTIMISTIC_FORCE_INCREMENT is used (for optimistic
locking).

In case it matters, I am using build time enhancement.  Here is the relevant
section from my Maven pom.xml file:

     <plugin>
        <groupId>org.apache.openjpa</groupId>
        <artifactId>openjpa-maven-plugin</artifactId>
        <version>${openjpa.version}</version>
        <configuration>
            <addDefaultConstructor>true</addDefaultConstructor>              
        </configuration>
        <executions>
            <execution>
                <id>enhancer</id>
                <phase>process-classes</phase>
                <goals>
                    <goal>enhance</goal>
                </goals>
            </execution>
        </executions>
        <dependencies>
            <dependency>
                <groupId>org.apache.openjpa</groupId>
                <artifactId>openjpa</artifactId>
                <version>${openjpa.version}</version>
            </dependency>
        </dependencies>
    </plugin>

Any help or advice would be greatly appreciated.


Thanks,


Alain




--
View this message in context: http://openjpa.208410.n2.nabble.com/Unecessary-database-update-tp7586121.html
Sent from the OpenJPA Users mailing list archive at Nabble.com.

Re: Unecessary database update?

Posted by Rick Curtis <cu...@gmail.com>.
Can you put together a small unit test[1] that recreates the issue?

[1] https://openjpa.apache.org/writing-test-cases-for-openjpa.html

Thanks,
Rick


On Sat, Mar 22, 2014 at 6:53 PM, Alain Brazeau <ab...@rogers.com> wrote:

> My application has the following bidirectional one-to-many association:
>
> @Entity
> @Table(name="TB_CUSTOMERS")
> public class Customer {
>
>     @OneToMany(mappedBy="customer", cascade={CascadeType.PERSIST,
> CascadeType.REMOVE})
>     @OrderBy("createdDate DESC")
>     private List<Order> orders = new ArrayList<Order>();
>
> ...
>
> }
>
> @Entity
> @Table(name="TB_ORDERS")
> public class Order {
>
>     @ManyToOne
>     @JoinColumn(name="CUSTOMER_ID")
>     private Customer customer;
>
> ...
>
> }
>
> I recently noticed that when a new Order object is added to a Customer
> object's Order List, the underlying Customer database table record gets
> updated, even though the Customer object was not modified.  This is
> especially problematic since I have a database trigger defined on the
> Customer table that inserts the old version of a record in a Customer
> history table for auditing purposes whenever an update occurs.
>
> I am currently using OpenJPA version 2.0.1.  I have tried upgrading to
> version 2.2.2, but still have the same problem.  If I use Hibernate instead
> of OpenJPA as the JPA implementation, the Customer database table does NOT
> get updated.
>
> Based on my understanding of JPA, the Customer record should not get
> updated
> unless LockModeType.OPTIMISTIC_FORCE_INCREMENT is used (for optimistic
> locking).
>
> In case it matters, I am using build time enhancement.  Here is the
> relevant
> section from my Maven pom.xml file:
>
>      <plugin>
>         <groupId>org.apache.openjpa</groupId>
>         <artifactId>openjpa-maven-plugin</artifactId>
>         <version>${openjpa.version}</version>
>         <configuration>
>             <addDefaultConstructor>true</addDefaultConstructor>
>         </configuration>
>         <executions>
>             <execution>
>                 <id>enhancer</id>
>                 <phase>process-classes</phase>
>                 <goals>
>                     <goal>enhance</goal>
>                 </goals>
>             </execution>
>         </executions>
>         <dependencies>
>             <dependency>
>                 <groupId>org.apache.openjpa</groupId>
>                 <artifactId>openjpa</artifactId>
>                 <version>${openjpa.version}</version>
>             </dependency>
>         </dependencies>
>     </plugin>
>
> Any help or advice would be greatly appreciated.
>
>
> Thanks,
>
>
> Alain
>
>
>
>
> --
> View this message in context:
> http://openjpa.208410.n2.nabble.com/Unecessary-database-update-tp7586121.html
> Sent from the OpenJPA Users mailing list archive at Nabble.com.
>



-- 
*Rick Curtis*

Re: Unecessary database update?

Posted by Rick Curtis <cu...@gmail.com>.
Yes, please.

Thanks,
Rick


On Thu, Mar 27, 2014 at 12:02 PM, Alain Brazeau <ab...@rogers.com> wrote:

> Thank you for your help Rick.
>
> Should I create a JIRA issue?
>
> Regards,
>
> Alain
>
>
>
> --
> View this message in context:
> http://openjpa.208410.n2.nabble.com/Unecessary-database-update-tp7586121p7586167.html
> Sent from the OpenJPA Users mailing list archive at Nabble.com.
>



-- 
*Rick Curtis*

Re: Unecessary database update?

Posted by Alain Brazeau <ab...@rogers.com>.
Thank you for your help Rick.  

Should I create a JIRA issue?

Regards,

Alain



--
View this message in context: http://openjpa.208410.n2.nabble.com/Unecessary-database-update-tp7586121p7586167.html
Sent from the OpenJPA Users mailing list archive at Nabble.com.

Re: Unecessary database update?

Posted by Rick Curtis <cu...@gmail.com>.
Alain -

I looked at your unit test and the reason that an extra update is being
sent to the database is because you're updating your Entity in the
@PreUpdate method. If you didn't update that field, no update would be
issued. That being said, I think we're getting down to the real problem.

I don't think @PreUpdate should be called in this instance because even
though Parent is dirty, it doesn't result in a DB update and as such,
@PreUpdate shouldn't be invoked. I thought we had a feature to control this
behavior, but I'm struggling to find it right now.

I'll attach my unit test for future reference.

Thanks,
Rick


On Tue, Mar 25, 2014 at 9:22 AM, Alain Brazeau <ab...@rogers.com> wrote:

> Hi Rick,
>
> As requested, here is a test I wrote in the 'openjpa-persistence-jdbc'
> project:
>
>
> package org.apache.openjpa.persistence.jdbc.update;
>
> import java.util.Date;
>
> import javax.persistence.EntityManager;
>
> import org.apache.openjpa.persistence.test.SingleEMFTestCase;
>
>
> public class TestCascadePersist extends SingleEMFTestCase {
>
>     public void setUp() throws Exception {
>         super.setUp(CLEAR_TABLES, Parent.class, Child.class);
>     }
>
>
>     public void testAddChildShouldNotUpdateParent() {
>         EntityManager em = emf.createEntityManager();
>
>         em.getTransaction().begin();
>         Parent parent = new Parent();
>         parent.setName("parent");
>         em.persist(parent);
>         em.getTransaction().commit();
>
>         long parentId = parent.getId();
>         Date expectedLastModifiedDate = parent.getLastModifiedDate();
>
>         em.getTransaction().begin();
>         parent = em.find(Parent.class, parentId);
>         parent.newChild("child");
>         em.getTransaction().commit();
>
>         Date actualModifiedDate = parent.getLastModifiedDate();
>
>         assertEquals("The last modified date should not change.",
>                      expectedLastModifiedDate.getTime(),
> actualModifiedDate.getTime());
>     }
>
> }
>
>
> In order for the test to work, the following instance variable and methods
> have to be added to the
> existing org.apache.openjpa.persistence.jdbc.update.Parent class:
>
>
>     private Date lastModifiedDate;
>
>     public Date getLastModifiedDate() {
>         return lastModifiedDate;
>     }
>
>     @PrePersist
>     @PreUpdate
>     public void onUpdate() {
>         this.lastModifiedDate = new Date();
>     }
>
>
> Thanks!
>
> Alain
>
>
>
> --
> View this message in context:
> http://openjpa.208410.n2.nabble.com/Unecessary-database-update-tp7586121p7586153.html
> Sent from the OpenJPA Users mailing list archive at Nabble.com.
>



-- 
*Rick Curtis*

Re: Unecessary database update?

Posted by Alain Brazeau <ab...@rogers.com>.
Hi Rick,

As requested, here is a test I wrote in the 'openjpa-persistence-jdbc'
project:


package org.apache.openjpa.persistence.jdbc.update;

import java.util.Date;

import javax.persistence.EntityManager;

import org.apache.openjpa.persistence.test.SingleEMFTestCase;


public class TestCascadePersist extends SingleEMFTestCase {
    
    public void setUp() throws Exception {
        super.setUp(CLEAR_TABLES, Parent.class, Child.class); 
    }    

    
    public void testAddChildShouldNotUpdateParent() {
        EntityManager em = emf.createEntityManager();

        em.getTransaction().begin();
        Parent parent = new Parent();
        parent.setName("parent");
        em.persist(parent);
        em.getTransaction().commit();
        
        long parentId = parent.getId();
        Date expectedLastModifiedDate = parent.getLastModifiedDate();
        
        em.getTransaction().begin();
        parent = em.find(Parent.class, parentId);
        parent.newChild("child");
        em.getTransaction().commit();
        
        Date actualModifiedDate = parent.getLastModifiedDate(); 

        assertEquals("The last modified date should not change.",
                     expectedLastModifiedDate.getTime(),
actualModifiedDate.getTime());        
    }

}


In order for the test to work, the following instance variable and methods
have to be added to the
existing org.apache.openjpa.persistence.jdbc.update.Parent class:


    private Date lastModifiedDate;
	
    public Date getLastModifiedDate() {
        return lastModifiedDate;
    } 
    
    @PrePersist
    @PreUpdate
    public void onUpdate() {
        this.lastModifiedDate = new Date();
    } 


Thanks!

Alain



--
View this message in context: http://openjpa.208410.n2.nabble.com/Unecessary-database-update-tp7586121p7586153.html
Sent from the OpenJPA Users mailing list archive at Nabble.com.