3

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

TotoroTotoro
  • 17,524
  • 4
  • 45
  • 76
Michael
  • 10,063
  • 18
  • 65
  • 104

2 Answers2

5

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.

jonathan.cone
  • 6,592
  • 2
  • 30
  • 30
1

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)

Bhesh Gurung
  • 50,430
  • 22
  • 93
  • 142
Baz1nga
  • 15,485
  • 3
  • 35
  • 61