Why not do the following wherever you use the p1 code?
p0 = em.find(Parent.class, p0.getId());
p0 = em.merge(p0);
Manfred
-----Original Message-----
From: glassfish_at_javadesktop.org [mailto:glassfish_at_javadesktop.org]
Sent: Tuesday, July 15, 2008 3:23 PM
To: users_at_glassfish.dev.java.net
Subject: Problem with JPA and cache
I'm having a problem with my J2EE application and after many hours of debugging
I have been able to distill the problem down into a small testable application.
My J2EE application consists of using the Command pattern and various Commands
can be strung together to accomplish a desired goal. These Commands when strung
together are executed within a Container Managed transaction and EntityManager.
This is the reason that the flow that I present below is done and I have no
easy way that I can change it.
Basically I have two entity classes: Parent and Child. Parent is created
with one Child automatically and other Child entities can be added. There
is a @OneToMany and @ManyToOne relationship between Parent and Child.
The problem that I am seeing is that I create a Parent, get another
handle to the parent using EntityManager.find, update the Parent,
create 3 more children for a total of 4, and commit. This commits fine
and the underlying database is correct. In a separate transaction, I find
the Parent and count the children which indicates that there are only
3 children instead of the 4 that are actually in the database.
From what I found, if I remove the @Version field on the parent, then
this problem goes away but then I cannot do optimistic locking.
Also in the code below, if I remove he "p1.setSerialNumber" invocation
the problem does not occur.
So I'm looking for some help into why this problem is occurring. I
think it has something to do with the @version and optimistic locking
but I don't know how to get around it.
Here is the main test application code. I build a small J2SE application
using user controlled transactions just for testing purposes and the
problem is still exhibited:
-- Main.java
package stest;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
public class Main {
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Integer id = create();
getCount(id);
}
public static Integer create() {
Integer id = null;
EntityManagerFactory emf = javax.persistence.Persistence.createEntityManagerFactory("stestPU");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
try {
Parent p0 = new Parent(false);
em.persist(p0);
em.flush();
Parent p1 = em.find(Parent.class, p0.getId());
// VVVVVV
p1.setSerialNumber("12345678");
// ^^^^^^
Child cs_1_1 = new Child();
p1.addChild(cs_1_1);
em.flush();
Child cs_1_2 = new Child();
p1.addChild(cs_1_2);
em.flush();
Parent chassis2 = em.find(Parent.class, p0.getId());
Child cs_2_1 = new Child();
chassis2.addChild(cs_2_1);
em.flush();
em.getTransaction().commit();
id = p1.getId();
} catch (Exception e) {
e.printStackTrace();
em.getTransaction().rollback();
} finally {
em.close();
}
return id;
}
public static void getCount(Integer id) {
EntityManagerFactory emf = javax.persistence.Persistence.createEntityManagerFactory("stestPU");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
try {
Parent chassis = em.find(Parent.class, id);
int count = chassis.getChildren().size();
System.out.println("config set count is " + count);
em.getTransaction().commit();
} catch (Exception e) {
e.printStackTrace();
em.getTransaction().rollback();
} finally {
em.close();
}
}
}
--
Here is the Parent Entity:
-- Parent.java
package stest;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Version;
@Entity
public class Parent implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column
private Integer id;
protected Parent() {
}
public Parent(boolean template) {
Child child = new Child();
addChild(child);
}
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
@Version
@Column
private int version;
public int getVersion() {
return version;
}
@OneToMany(mappedBy = "parent", cascade = {CascadeType.ALL})
private List<Child> children = new ArrayList<Child>();
public List<Child> getChildren() {
return children;
}
public void setChildren(List<Child> children) {
this.children = children;
}
public void addChild(Child cs) {
cs.setParent(this);
this.children.add(cs);
}
@Column
private String serialNumber;
public String getSerialNumber() {
return this.serialNumber;
}
public void setSerialNumber(String serialNumber) {
this.serialNumber = serialNumber;
}
}
--
Here is the Child entity:
-- Child.java
package stest;
import java.io.Serializable;
import java.util.Date;
import javax.persistence.CascadeType;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Temporal;
import javax.persistence.TemporalType;
import javax.persistence.Version;
@Entity
public class Child implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column
private Integer id;
public Child() {
}
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
@Version
@Column
private int version;
public int getVersion() {
return version;
}
@ManyToOne(cascade = {CascadeType.ALL})
private Parent parent;
public Parent getParent() {
return parent;
}
public void setParent(Parent parent) {
this.parent = parent;
}
@Temporal(TemporalType.TIMESTAMP)
@Column
private Date createdOn = new Date();
public Date getCreatedOn() {
return this.createdOn;
}
protected void setCreatedOn(Date createdOn) {
this.createdOn = createdOn;
}
}
[Message sent by forum member 'bbergquist' (bbergquist)]
http://forums.java.net/jive/thread.jspa?messageID=286859
---------------------------------------------------------------------
To unsubscribe, e-mail: users-unsubscribe_at_glassfish.dev.java.net
For additional commands, e-mail: users-help_at_glassfish.dev.java.net