I'm trying to implement EHCache into my working prototype, where I have a javax.persistence.Entity representing a table on my database (MySQL, mysql-connector-java-5.1.20.jar), which be provided as XML to the consumers.
The issue I'm facing is that seems Hibernate still retrieving the data from the database, even when EHCache stores the query result on memory.
I'm using the EHCache monitor to see the count of items in memory, and changing the data directly on database before the cache expires to know if the cached data is actually used.
I been looking for a replication for this issue without succeed, so maybe I'm missing something (I just geting into the java world).
pom.xml
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>4.3.0.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-entitymanager</artifactId>
<version>4.1.4.Final</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-ehcache</artifactId>
<version>4.1.4.Final</version>
</dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>2.5.2</version>
</dependency>
<dependency>
<groupId>org.terracotta</groupId>
<artifactId>ehcache-probe</artifactId>
<version>1.0.2</version>
</dependency>
Entity class
package myPrototype.entities
import javax.persistence.Cacheable;
import javax.persistence.Entity;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.Table;
import javax.xml.bind.annotation.XmlRootElement;
import org.hibernate.annotations.Cache;
import org.hibernate.annotations.CacheConcurrencyStrategy;
@Entity @Cacheable
@Cache(usage=CacheConcurrencyStrategy.READ_ONLY)
@Table(name = "Cars")
@XmlRootElement
@NamedQueries({
@NamedQuery(name = "Cars.findAll", query = "SELECT d FROM Cars d"),
[...]
public class Cars implements Serializable {
private static final long serialVersionUID = 1L;
@Basic(optional = false)
@NotNull
@Column(name = "id")
@ReferenceField
private int id;
[...]
ehcache.xml
<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
<cache name="myPrototype.entities.Cars"
maxElementsInMemory="500"
eternal="false"
overflowToDisk="false"
timeToIdleSeconds="60"
timeToLiveSeconds="120" />
</ehcache>
* I tried setting eternal="true", but the result still the same
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="MyPrototype" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:app/jdbc/mysqlserver/prototype</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<shared-cache-mode>ENABLE_SELECTIVE</shared-cache-mode>
<properties>
<!-- property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.SingletonEhCacheRegionFactory"/ -->
<property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.ehcache.EhCacheRegionFactory" />
<property name="hibernate.cache.use_second_level_cache" value="true"/>
<property name="hibernate.cache.use_query_cache" value="true"/>
<property name="hibernate.cache.region_prefix" value=""/>
</properties>
</persistence-unit>
</persistence>
* I tried switching between SingletonEhCacheRegionFactory and EhCacheRegionFactory
EJB
import myPrototype.entities.Cars
import java.util.Date;
import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
@Stateless
public class CarsEJB {
@PersistenceContext(unitName="MyPrototype")
private EntityManager em;
@Override
public List<Cars> getCars() {
return (List<Cars>)em.createNamedQuery("Cars.findAll").setMaxResults(200).getResultList();
}
}
* Added to clarify how I run the query
Like I said, I can see a count of items in memory through EHCache monitor, so I noted the following: - The ehcache configuration is property loaded elements are expiring - The elements expiration not being reseted when the query runs while they still alive (they expired N seconds after the first query).
Again; I'm quite a newbie with java, so asume I could be missing basic concepts.
Thanks for reading!
Hibernate will never execute queries on your cache. What it can do is execute a query on the database, cache the results, and return these cached results the next time you execute the same query, with the same parameters. But to do that, the query, each time it's executed, must be cacheable.
WIth the JPA API, this is done using query hints, directly on the named query definition, or each time you create a query:
@NamedQuery(name = "Cars.findAll",
query = "SELECT d FROM Cars d",
hints = {@QueryHint(name = "org.hibernate.cacheable", value = "true")})
Now that the query is cacheable, Hibernate will load the IDs of the cars from the database the first time this query is executed, and from the query cache afterwards. Then the corresponding cars themselves will be loaded from the entity cache.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With