Search code examples
jakarta-eejpajpa-2.0eclipselink

Eclipselink shared cache between threads


Here is my configuration, first persistence.xml:

<persistence 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"
    version="2.0">     
<persistence-unit name="db" transaction-type="RESOURCE_LOCAL">
    <provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
        <!-- This is needed to allow it to find entities by annotations -->
    <exclude-unlisted-classes>false</exclude-unlisted-classes>
    <shared-cache-mode>ALL</shared-cache-mode> 

    <properties>
    <property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver"/>
        <property name="javax.persistence.jdbc.user" value="user"/>
        <property name="javax.persistence.jdbc.password" value="password"/>
        <property name="javax.persistence.jdbc.url" value="jdbc:mysql://ip/dbname"/>

        <property name="eclipselink.logging.level" value="FINEST"/>     
        <property name="eclipselink.weaving" value="static"/>
        <property name="eclipselink.cache.type.default" value="SoftWeak"/>

    </properties>
</persistence-unit>
</persistence>

Here is how I create my EntityManagerFactory.

private static EntityManagerFactory factory = null;

public synchronized static DBStore getInstance() {
    if (factory == null) {
        factory = Persistence.createEntityManagerFactory("db");
    }
    return new DBStore(factory.createEntityManager());
}

where DBStore is the object which I use as a middle man to access the EntityManager.

Using EclipseLink 2.4

And here is the problem. If I create thread 1, get a DBStore object for it, make some changes to an existing entity, commit them to the database, and I have another concurrent thread (2) load that same entity before and after the change was made and committed, the second thread does not see the changes committed by the first thread. I know the changes are in the database because I can see them. Also if on the second thread I call EntityManager.refresh(entity) before checking the values of the the entity, then it works fine. So my guess here is that my two threads are not sharing their cache with each other even though EclipseLink is supposed to do that if you use the same EntityManagerFactory, which I am considering it is static.

So what is wrong with my setup?


Solution

  • Each EntityManager has its own cache as they are meant to represent separate transaction contexts. So pre existing entities read into an EntityManager will not show changes from others unless refreshed or the EM is cleared and the entity reread. Eclipselink caching with respect to JPA is described here: http://wiki.eclipse.org/EclipseLink/Examples/JPA/Caching