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

有帮助吗?

解决方案

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.

其他提示

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)

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top