Hibernate 4 с кешем второго уровня: что не так в моем понимании?

Я начинаю использовать Hibernate 4 с кешем второго уровня. Согласно документации, конфигурация была очень простой:

<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>

Насколько я понимаю, кеш второго уровня должен исключать одинаковые запросы к базе данных. У меня очень простой объект и очень простой именованный запрос:

@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;
    }



}

Я запускаю именованный запрос 4 раза и, к сожалению, вижу, что спящий режим запускает его 4 раза.

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();

Выход:

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=?

Что не так с чем не так в моем понимании кэша второго уровня? Почему Hibernate выполняет запрос 4 раза? Я пропустил некоторые конфигурации?

Заранее спасибо, Михаил


person Michael    schedule 22.07.2012    source источник


Ответы (2)


Метод setCacheable недоступен из javax.persistence.Query, поэтому вам нужно добавить подсказку кэширования в именованный запрос (или вызвать setHint):

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

Тем не менее, использование кеша запросов прыгнуло с акулы, следующая статья обязательна к прочтению если ты вообще собираешься это рассматривать. В наши дни есть лучшие подходы, такие как абстракция Spring Caching.

person jonathan.cone    schedule 22.07.2012
comment
+1 за потрясающую статью и объяснение кеша запросов. - person cbmeeks; 23.08.2013

Разве вы не должны также иметь следующее в своей конфигурации:

<cache usage="read-write"/>

Также я забыл, что вам нужно либо установить свойство cacheable="true" для именованного запроса, либо setCacheable(true) при выполнении самого запроса.

PS: не уверен, какой синтаксис в спящем режиме, но в Nhibernate его SetCacheable (true)

person Baz1nga    schedule 22.07.2012