I have a simple data model which consists of a parent object with a one-to-many relationship to a list of child objects.
@Entity
public class Client implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany(cascade = CascadeType.ALL)
private List<Session> sessions;
...
}
@Entity
public class Session implements Serializable {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(length = 200)
private String location;
...
}
I have enabled L2 caching using OpenJpa in the persistence.xml:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.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_2_0.xsd">
<persistence-unit name="puOpenJPA_Gym" transaction-type="JTA">
<provider>org.apache.openjpa.persistence.PersistenceProviderImpl</provider>
<jta-data-source>java:jboss/datasources/GymTracker</jta-data-source>
<class>za.co.blacklemon.entities.Client</class>
<class>za.co.blacklemon.entities.Session</class>
<shared-cache-mode>ALL</shared-cache-mode>
<properties>
<property name="openjpa.jdbc.SynchronizeMappings" value="buildSchema(ForeignKeys=true)"/>
<property name="jboss.as.jpa.providerModule" value="org.apache.openjpa"/>
<property name="openjpa.DynamicEnhancementAgent" value="false"/>
<property name="openjpa.Log" value="File=stdout, DefaultLevel=WARN, Runtime=INFO, Tool=INFO, SQL=TRACE"/>
<property name="openjpa.QueryCache" value="true(CacheSize=10000, SoftReferenceSize=1000)"/>
<property name="openjpa.DataCache" value="true(CacheSize=20000, SoftReferenceSize=1000)"/>
</properties>
</persistence-unit>
</persistence>
I then get individual clients by calling find and then accessing the list of sessions. The second line here triggers OpenJPA to populate the child objects from the DB:
Client client = dao.find(Client.class, id);
System.out.println(client.getSessions().size());
The first time this runs there appears two queries in the log, one for the parent object and one each for any children:
executing prepstmnt 782097742 SELECT t0.contactNumber, t0.description, t0.firstName, t0.photo, t0.surname FROM Client t0 WHERE t0.id = ? [params=?]
executing prepstmnt 626498798 SELECT t1.id, t1.location FROM Client_Session t0 INNER JOIN Session t1 ON t0.SESSIONS_ID = t1.id WHERE t0.CLIENT_ID = ? [params=?]
The second time this runs the initial query is gone, as the object is retrieved from the cache, but the second (and possibly more) query is still executed.
Why does OpenJPA not store the child objects in a one-to-many relationship in the cache?
I'm using OpenJPA 2.3.0 on Java 7.
OpenJPA stores the child objects, but it doesn't store the FK back into the parent. I fixed this problem in OpenJPA trunk(2.4.x) via OPENJPA-2285.