Here is an OpenJPA 1.2.1 example that demonstrates the "OpenJPA replaces
a collection field" problem. This may not be technically a bug but it
can be a problem for the unaware user.
This happens with a new persisted object with a collection field that is
initially null. If the null collection is initialized to an empty
collection it will correctly register additions until it is flushed.
Then the collection field is replaced and the old collection is stale.
In this example the flush is an explicit call. But the same problem
happens when the object is implicitly flushed to get the generated
identity for a foreign key.
In the main program the behavior changes when "em.flush()" is commented out.
================= LazyLoadTest.java ==============
package com.jpatest;
import javax.persistence.*;
import java.util.*;
import com.jpatest.persistence.*;
public class LazyLoadTest
{
public static void main(String args[])
throws Throwable
{
EntityManagerFactory emf =
Persistence.createEntityManagerFactory("jpatest");
EntityManager em = emf.createEntityManager();
em.getTransaction().begin();
ListHolder holder = new ListHolder();
em.persist(holder);
List<ListMember> listReference = holder.getMembers();
em.persist(new ListMember(holder));
System.err.println("id="+holder.id+"
size[expect=1]="+listReference.size());
em.persist(new ListMember(holder));
System.err.println("id="+holder.id+"
size[expect=2]="+listReference.size());
em.flush(); // **** this causes problem when uncommented
em.persist(new ListMember(holder));
System.err.println("id="+holder.id+"
size[expect=3]="+listReference.size());
em.getTransaction().commit();
em.close();
}
}
================= ListHolder.java ==============
package com.jpatest.persistence;
import java.util.*;
import javax.persistence.*;
@Entity
@Table (name="list_holder")
public class ListHolder
implements java.io.Serializable
{
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Id public long id;
@Version private long version;
@OneToMany(mappedBy="holder", fetch=FetchType.LAZY,
cascade={CascadeType.PERSIST,CascadeType.REMOVE})
private List<ListMember> members;
public ListHolder() {}
public List<ListMember> getMembers()
{
if (members == null) {
System.err.println("---- ListHolder members == null");
members = new ArrayList<ListMember>();
}
return members;
}
}
================= ListMember.java ==============
package com.jpatest.persistence;
import javax.persistence.*;
@Entity
@Table (name="list_member")
public class ListMember
implements java.io.Serializable
{
@GeneratedValue(strategy=GenerationType.IDENTITY)
@Id private long id;
@Version private long version;
@ManyToOne (optional=false,fetch=FetchType.LAZY,cascade=CascadeType.ALL)
private ListHolder holder;
protected ListMember() {}
public ListMember(ListHolder holder)
{
this.holder = holder;
holder.getMembers().add(this);
}
}