Ruben Laguna’s blog

OpenJPA: Generated SQL Contains Extra UPDATEs

I’m trying to use OpenJPA to insert some entries in the database and I’m getting a strange number of @UPDATE@s beside the @INSERT@s.

I isolated the problem to the following snippet of code

1
2
3
4
5
6
7
8
9
10
11

1
2
3
4
5
6
7
8
9
10
11
<span class='line'>private void start() {
</span><span class='line'>        EntityManagerFactory emf = Persistence.createEntityManagerFactory("persistencexmltest1PU");
</span><span class='line'>        EntityManager em = emf.createEntityManager();        
</span><span class='line'>        for (int i = 0; i &lt; 10; i++) {
</span><span class='line'>            em.getTransaction().begin();
</span><span class='line'>            MyEntity n =new MyEntity();
</span><span class='line'>            n.setValue(i);
</span><span class='line'>            em.persist(n);        
</span><span class='line'>            em.getTransaction().commit();
</span><span class='line'>        }
</span><span class='line'>    }</span>

The generated SQL looks like this:

INSERT INTO MYTABLE (ID, VALUE, CREATED) VALUES (?, ?, ?) [params=(int) 1, (int) 0, (null) null]
INSERT INTO MYTABLE (ID, VALUE, CREATED) VALUES (?, ?, ?) [params=(int) 2, (int) 1, (null) null]
UPDATE MYTABLE SET CREATED = ? WHERE ID = ? [params=(null) null, (int) 1]
INSERT INTO MYTABLE (ID, VALUE, CREATED) VALUES (?, ?, ?) [params=(int) 3, (int) 2, (null) null]
UPDATE MYTABLE SET CREATED = ? WHERE ID = ? [params=(null) null, (int) 2]
UPDATE MYTABLE SET CREATED = ? WHERE ID = ? [params=(null) null, (int) 1]
INSERT INTO MYTABLE (ID, VALUE, CREATED) VALUES (?, ?, ?) [params=(int) 4, (int) 3, (null) null]
UPDATE MYTABLE SET CREATED = ? WHERE ID = ? [params=(null) null, (int) 3]
UPDATE MYTABLE SET CREATED = ? WHERE ID = ? [params=(null) null, (int) 2]
UPDATE MYTABLE SET CREATED = ? WHERE ID = ? [params=(null) null, (int) 1]
INSERT INTO MYTABLE (ID, VALUE, CREATED) VALUES (?, ?, ?) [params=(int) 5, (int) 4, (null) null]
UPDATE MYTABLE SET CREATED = ? WHERE ID = ? [params=(null) null, (int) 3]
UPDATE MYTABLE SET CREATED = ? WHERE ID = ? [params=(null) null, (int) 4]
UPDATE MYTABLE SET CREATED = ? WHERE ID = ? [params=(null) null, (int) 2]
UPDATE MYTABLE SET CREATED = ? WHERE ID = ? [params=(null) null, (int) 1]
INSERT INTO MYTABLE (ID, VALUE, CREATED) VALUES (?, ?, ?) [params=(int) 6, (int) 5, (null) null]
UPDATE MYTABLE SET CREATED = ? WHERE ID = ? [params=(null) null, (int) 3]
UPDATE MYTABLE SET CREATED = ? WHERE ID = ? [params=(null) null, (int) 4]
UPDATE MYTABLE SET CREATED = ? WHERE ID = ? [params=(null) null, (int) 2]
UPDATE MYTABLE SET CREATED = ? WHERE ID = ? [params=(null) null, (int) 5]
UPDATE MYTABLE SET CREATED = ? WHERE ID = ? [params=(null) null, (int) 1]
...

pay attention to the extra UPDATE statements after each INSERT, the number of extra @UPDATE@s grows as well. From zero @UPDATE@s after the first INSERT, one in the second, two in the third, and so on. I don’t need to say that this is of course really inefficient. I don’t know what is ultimate cause of this but this started when I added a @Temporal(TemporalType.TIMESTAMP) annotation to the entity class. And I can make it go away by calling EntityManager.clear() after each em.getTransaction().commit()

UPDATE: Ok I found a bug report stating that this behaviour is only observed when the entity classes are not enhanced. . So the best solution is use the enhancer. But it really doesn’t work for me, I still get the extra UPDATEs even with enhanced classes. So I’m stuck with the EntityManager.clear() for now.. If the class is PROPERLY ENHANCED the problem goes away.

Check the logs (enable them with <property name="openjpa.Log" value="DefaultLevel=TRACE"/> in persistence.xml) and make sure that you don’t see any entry like

5968  persistencexmltest1PU  INFO   [main] openjpa.Enhance - Creating subclass for "[class com.rubenlaguna.MyEntity]". This means that your application will be less efficient and will consume more memory than it would if you ran the OpenJPA enhancer. Additionally, lazy loading will not be available for one-to-one and many-to-one persistent attributes in types using field access; they will be loaded eagerly instead.

If you see the Creating subclass for message means that the class wasn’t enhanced, as I read OpenJPA really need enhanced classes, un – enhanced are just for testing and trivial examples.+

For reference:

persistence.xml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
<span class='line'>&lt;?xml version="1.0" encoding="UTF-8"?>
</span><span class='line'>&lt;persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
</span><span class='line'>  &lt;persistence-unit name="persistencexmltest1PU" transaction-type="RESOURCE_LOCAL">
</span><span class='line'>    &lt;provider>org.apache.openjpa.persistence.PersistenceProviderImpl&lt;/provider>
</span><span class='line'>    &lt;class>com.rubenlaguna.MyEntity&lt;/class>
</span><span class='line'>    &lt;properties>
</span><span class='line'>      &lt;property name="openjpa.ConnectionPassword" value=""/>
</span><span class='line'>      &lt;property name="openjpa.ConnectionDriverName" value="org.hsqldb.jdbc.JDBCDriver"/>
</span><span class='line'>      &lt;property name="openjpa.ConnectionUserName" value="sa"/>
</span><span class='line'>      &lt;property name="openjpa.ConnectionURL" value="jdbc:hsqldb:file:/Users/ecerulm/everjavatest"/>
</span><span class='line'>      &lt;property name="openjpa.Log" value="SQL=TRACE"/>
</span><span class='line'>      &lt;property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(SchemaAction=&apos;add,deleteTableContents&apos;,ForeignKeys=true)"/>
</span><span class='line'>    &lt;/properties>
</span><span class='line'>  &lt;/persistence-unit>
</span><span class='line'>&lt;/persistence></span>

MyEntity.java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
<span class='line'>/*
</span><span class='line'> * To change this template, choose Tools | Templates
</span><span class='line'> * and open the template in the editor.
</span><span class='line'> */
</span><span class='line'>
</span><span class='line'>package com.rubenlaguna;
</span><span class='line'>
</span><span class='line'>import java.util.Date;
</span><span class='line'>import javax.persistence.Column;
</span><span class='line'>import javax.persistence.Entity;
</span><span class='line'>import javax.persistence.GeneratedValue;
</span><span class='line'>import javax.persistence.GenerationType;
</span><span class='line'>import javax.persistence.Id;
</span><span class='line'>import javax.persistence.Table;
</span><span class='line'>import javax.persistence.Temporal;
</span><span class='line'>import javax.persistence.TemporalType;
</span><span class='line'>
</span><span class='line'>/**
</span><span class='line'> *
</span><span class='line'> * @author Ruben Laguna &lt;ruben.laguna at gmail.com>
</span><span class='line'> */
</span><span class='line'>@Entity
</span><span class='line'>@Table(name = "MYTABLE")
</span><span class='line'>public class MyEntity {
</span><span class='line'>    @Id
</span><span class='line'>    @Column(name = "ID")
</span><span class='line'>    @GeneratedValue(strategy=GenerationType.AUTO)
</span><span class='line'>    private Integer id;
</span><span class='line'>
</span><span class='line'>
</span><span class='line'>    @Column(name = "VALUE")
</span><span class='line'>    private Integer attr1;
</span><span class='line'>
</span><span class='line'>
</span><span class='line'>    @Column(name = "CREATED")
</span><span class='line'>    @Temporal(TemporalType.TIMESTAMP)
</span><span class='line'>    private Date created;
</span><span class='line'>
</span><span class='line'>
</span><span class='line'>    public Integer getId() {
</span><span class='line'>        return id;
</span><span class='line'>    }
</span><span class='line'>
</span><span class='line'>    public void setId(Integer id) {
</span><span class='line'>        this.id = id;
</span><span class='line'>    }
</span><span class='line'>
</span><span class='line'>    public Integer getValue() {
</span><span class='line'>        return attr1;
</span><span class='line'>    }
</span><span class='line'>
</span><span class='line'>    public void setValue(Integer value) {
</span><span class='line'>        this.attr1 = value;
</span><span class='line'>    }
</span><span class='line'>
</span><span class='line'>}</span>

References:

Comments

Copyright © 2015 - Ruben Laguna - Powered by Octopress