Question

I have starting to use Hibernate 4 with second level cache. The configuration was very simple according to the documentation:

<property name="hibernate.cache.use_second_level_cache"  value="true"></property>
<property name="hibernate.cache.use_query_cache"  value="true"></property>
<property name="hibernate.cache.region.factory_class"  value="org.hibernate.cache.ehcache.EhCacheRegionFactory"></property>

According to my understanding the second level cache should eliminate same queries to the database. I have very simple entity and very simple named query:

@Entity
@NamedQueries({
        @NamedQuery(name="SimplePerson.findByName", query="select p from SimplePerson p where p.name = :name"),
})

@Cache(usage = CacheConcurrencyStrategy.READ_WRITE)
public class SimplePerson {

    public static final String FIND_BY_NAME = "SimplePerson.findByName";

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private int id;

    private String name;

    public SimplePerson() {

    }

    public SimplePerson(String name) {
        this.name = name;
    }



}

I run named query 4 times and unfortunately I see that hibernate run it 4 times.

EntityManagerFactory emf = Persistence.createEntityManagerFactory("test");      
EntityManager em = emf.createEntityManager();

Query query = em.createNamedQuery(SimplePerson.FIND_BY_NAME);
query.setParameter("name", "BOB");

List result = query.getResultList();
result = query.getResultList();
result = query.getResultList();
result = query.getResultList();

The output:

Hibernate: select simplepers0_.id as id0_, simplepers0_.name as name0_ from SimplePerson simplepers0_ where simplepers0_.name=?
Hibernate: select simplepers0_.id as id0_, simplepers0_.name as name0_ from SimplePerson simplepers0_ where simplepers0_.name=?
Hibernate: select simplepers0_.id as id0_, simplepers0_.name as name0_ from SimplePerson simplepers0_ where simplepers0_.name=?
Hibernate: select simplepers0_.id as id0_, simplepers0_.name as name0_ from SimplePerson simplepers0_ where simplepers0_.name=?

What wrong with what wrong in my understanding of the second level cache? Why Hibernate runs the query 4 times? Do I miss some configurations?

Thanks in advance, Michael

Was it helpful?

Solution

The setCacheable method is not available from javax.persistence.Query, so you'll need to add the caching hint to the named query (or call setHint):

@NamedQueries({
@NamedQuery(
    name="SimplePerson.findByName", 
    query="select p from SimplePerson p where p.name = :name", 
    hints = { @QueryHint(name = "org.hibernate.cacheable", value = "true") })
})

That said, using the query cache has jumped the shark, the following article is a must read if you're even going to consider it. These days there are better approaches like the Spring Caching abstraction.

OTHER TIPS

Shouldn't you also have the following in your configuration:

<cache usage="read-write"/>

Also I forgot you need to either set the cacheable="true" property on the named query or setCacheable(true) while running the query itself.

P.S: not sure what the syntax is in hibernate but in Nhibernate its SetCacheable(true)

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top