javajava-8eclipselinkpayara

Caching Embedded Entities


I am currently working on a project for my company. using Payara 5.201 and Eclipselink 2.6 (technically (org.eclipse.persistence:org.eclipse.persistence.jpa:2.6.4). The Payara instance is local to my machine but the database has to be connected to through a VPN. In the project there are a few entities that are just for looking up values. I am looking for a way to have the values for the lookup table retrieved from the database once while keeping a local copy for the duration of a method.

The lookup entity is listed below, and it has been edited for space and clarity.

@Entity
@Table(name = "fapermittypes")
@Cache(  //not sure if this works
  type=CacheType.SOFT, // Cache everything until the JVM decides memory is low.
  size=10000,  // Use 10,000 as the initial cache size.
  expiry=300000,  // 5 minutes
  isolation=CacheIsolationType.SHARED,
  coordinationType=CacheCoordinationType.INVALIDATE_CHANGED_OBJECTS  // if cache coordination is used, only send invalidation messages.
)
@NamedQueries({
    @NamedQuery(name = "PermitType.findAll", query = "SELECT n FROM PermitType n"),
    @NamedQuery(name = "PermitType.findByName", query = "SELECT n FROM PermitType n WHERE n.permittype = :permittypeName")
})
public class PermitType implements Serializable {
    private static final long serialVersionUID = 1L;

    @Id
    @Column(name="permittype")
    private String permitType;

    @Column(name="permittypedesc")
    private String permitTypeDescription;

    ...
}

And the Entity that references this entity is listed below.

@Entity
@Table(name = "myTable")
@NamedQueries({
    @NamedQuery(name = "Permit.findAll", query = "SELECT n FROM Permit n"),
    @NamedQuery(name = "Permit.findBytheName", query = "SELECT n FROM Permit n WHERE n.PermitPK.theName = :theName"),
})
public class Permit implements Serializable {

    private static long serialVersionUID = 1L;

    @EmbeddedId
    private PermitPK PermitPK;

    ...

    @ManyToOne
    @JoinColumns({
        @JoinColumn(name = "permittype", referencedColumnName = "permittype", insertable = false, updatable = false)
    })
    private PermitType permitType;
    ...
}

When I deploy the WAR to Payara 5.201 with monitoring turned on, I noticed that it is hitting the database a lot. Below is a sample from the log output.

FINE:   SELECT permittype, permittypedesc FROM fapermittypes WHERE (permittype = ?)
    bind => [GENERAL]
FINE:   SELECT permittype, permittypedesc FROM fapermittypes WHERE (permittype = ?)
    bind => [GENERAL]
FINE:   SELECT permittype, permittypedesc FROM fapermittypes WHERE (permittype = ?)
    bind => [GENERAL]
FINE:   SELECT permittype, permittypedesc FROM fapermittypes WHERE (permittype = ?)
    bind => [GENERAL]
FINE:   SELECT permittype, permittypedesc FROM fapermittypes WHERE (permittype = ?)
    bind => [GENERAL]
FINE:   SELECT permittype, permittypedesc FROM fapermittypes WHERE (permittype = ?)
    bind => [GENERAL]
FINE:   SELECT permittype, permittypedesc FROM fapermittypes WHERE (permittype = ?)
    bind => [GENERAL]
FINE:   SELECT permittype, permittypedesc FROM fapermittypes WHERE (permittype = ?)
    bind => [GENERAL]

I realize that internally the entity is using a JDBC prepared statement and binding the parameter, but is there some way to keep a local cache of the result for the duration of a method. There is a lot of repetitive queries going on behind the scenes for different entities that contain the object. The result of the JDBC queries above with be the same object. Is there a way to have the entity manager use a local cache for certain embedded entities when it is fetching them from the database. I would like to have something like:

public void myProcessingMethod() {
    // start local cache
    doStuff()
    // stop cache and free up objects.
}

Is there a way to accomplish this?
Joe


Solution

  • If I understand correctly, your main problem is that you want to create a custom caching system for your entities. This can be achieved by editing your persistence.xml file and adding lines like this:

    <property name="eclipselink.cache.shared.Entity1" value="None"/>
    <property name="eclipselink.cache.shared.Entity2" value="None"/>
    <property name="eclipselink.cache.shared.Entity3" value="Full"/>
    

    So with the above the entityManager will always fetch the Entity1 and Entity2 from the database and keep the Entity3 in memory (local cache). This would help you Understanding EclipseLink, 2.6