Home » Eclipse Projects » EclipseLink » Caching or Something else(Entity Efficiency)
Caching or Something else [message #1860920] |
Fri, 08 September 2023 19:09  |
Joseph McCay Messages: 1 Registered: September 2023 |
Junior Member |
|
|
I have two Entities. One references a table that is primarily for looking up values and descriptions. This table structure is a legacy table structure, so I can't change the structure. I am using Eclipselink 2.6. Technically it is org.eclipse.persistence:org.eclipse.persistence.jpa:2.6.4 with Payara 5.201 as the server.
The basics for the Entity class for the lookup table is listed below. I have edited it for brevity. I don't think the caching is working.
@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;
...
}
The Entity that contains the many to one reference is listed below. Again, I have edited it for brevity.
@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;
...
}
My Payara instance is on my local machine, but the database is connected to over a VPN. I deployed the war file to my Payara server, and I turned on Monitoring for some stuff. Included in the monitoring I turned on was monitoring of JDBC to high. I noticed the following in the 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 the JDBC statement has probably been prepared, and I also realize it is probably reusing the same prepared statement with the parameter being bound to it. The code is retrieving the same object several times from the database. It just seems like a waste of time. Is there a way the program can keep a local cache of the PermitType for just the lifetime of a single method that the entity manager will use to get the PermitType object locally if it exists. If it doesn't exist, retrieve it from the database storing a local copy for future references. The goal is to have it only retrieve from the database once since it can be costly. Something like:
public void process() {
// start local cache
runMyprocesses();
// stop and clear the local cache
Thank you in advance.
Joe
|
|
|
Re: Caching or Something else [message #1860973 is a reply to message #1860920] |
Tue, 12 September 2023 14:58  |
Chris Delahunt Messages: 44 Registered: December 2021 |
Member |
|
|
There is a shared cache by default, so you should see caching with or without that annotation - all it does is change some of the setting for that one class. See https://eclipse.dev/eclipselink/documentation/2.5/jpa/extensions/a_cache.htm#:~:text=The%20EclipseLink%20cache%20is%20an,memory%20to%20minimize%20database%20access for info - I don't think specifying a size with a CacheType.SOFT does anything. Everything gets put in an identity map with Full, soft or weak options with no limit. You might want to look at SOFT_WEAK, the default which maintains a cache with a fixed size using soft references, and weak references on everything else. Also note the named "PermitType.findByName" is incorrect - it has the wrong case for n.permittype which I hope is just a typing mistake when copying. Since this is the same as a findById, the query doesn't seem to be necessary anyway.
As for the duplicate statements: you've filtered out the timestamps and other logs message, so we can't tell how frequently they are occurring or in what contexts. There are many reasons for an object to not be in the shared cache requiring it to be fetched from the database, and there are two levels of caching - the shared cache, and then the 1st level cache (at within the EntityManager or UnitOfWork). If these reads are performed through their own EntityManagers in their own transactions where data modification might have occurred, the shared data cannot be used, and the object is not immediately put in the shared cache so that transactional data doesn't pollute the shared cache. Course, it could be a custom query - something just returning the permitType and permitTypeDescription instead of the managed (and so cached) PermitType entity. You'll have to check out the processes doing the loading and see what settings they are using to determine what can be done to reduce this overhead.
Best Regards,
Chris
|
|
|
Goto Forum:
Current Time: Fri Dec 08 02:23:17 GMT 2023
Powered by FUDForum. Page generated in 0.02169 seconds
|