Как getHibernateTemplate (). SetCacheQueries () должен использоваться правильно? - PullRequest
3 голосов
/ 17 августа 2011

В некоторой части нашего кода мы используем метод setCacheQueries () HibernateDaoSupport. Сначала у нас была функция getByGroupId(), которая просто называлась setCacheQueries(true), но при проведении интеграционного тестирования это приводило к тому, что Hibernate выдавал «двойные исключения». Поэтому я немного погуглил и увидел, что многие использовали шаблон, в котором они включали кеш, прежде чем выполнять запрос и затем отключать его. Затем я попытался отключить кэширование после запроса, и ошибка дублирования исчезла. Теперь мне интересно, что на самом деле делает этот шаблон? Код ниже смоделирован по этому шаблону.

import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
public class MyDao extends HibernateDaoSupport{

  public List getByGroupId(Long groupId) {
    getHibernateTemplate().setCacheQueries(true);
    List result = getHibernateTemplate().find(
                    "from Selection where groupId = ? order by sortOrder ASC", groupId);
    getHibernateTemplate().setCacheQueries(false);
    return result;
  }
}

Я не уверен, как Spring и Hibernate работают здесь вместе. Если бы setCacheQueries(false) очистил бы все кэшированные запросы, это не имело бы смысла, но если бы он просто отключил кэширование более поздних запросов (пока не будет вызван setCacheQueries(true)), это имело бы немного больше смысла.

  • Является ли этот шаблон включения / выключения кэширования до и после выполнения запросов нормальным?
  • Работает ли это (т.е. кешируются ли запросы)?
  • Есть идеи, почему Hibernate генерирует исключения для повторяющихся записей, когда не вызывает setCacheQueries(false) после запроса?

Ответы [ 2 ]

8 голосов
/ 17 августа 2011

Когда свойство cacheQueries HibernateTemplate имеет значение true, оно автоматически заставляет каждый Query или Criteria выполнять кэширование.Т.е. он вызывает Query.setCacheable (true) и Criteria.setCacheable (true) перед выполнением запроса / критериев.

Итак, ваш шаблон на самом деле состоит в том, чтобы сделать запрос, который вы собираетесь выполнить, кэшируемым, а затем сбросить флаг на false, чтобы следующий запрос не был сделан кэшируемым.

Проблемав том, что если HibernateTemplate используется несколькими потоками, результаты использования этого шаблона являются неопределенными.Возможно, поток установит для флага значение true, а затем другой сразу же сбросит его до false, прежде чем первый поток успеет выполнить свой запрос.А поскольку доступ к свойству не синхронизирован, у вас также могут быть проблемы с видимостью.

Я бы использовал HibernateTemplate.setCacheable(true) только при создании HibernateTemplate, чтобы убедиться, что all выполняемые запросы кешируются.Если вы этого не хотите, то используйте два разных экземпляра HibernateTemplate (один с включенным кешем, а другой без него) или используйте API Hibernate напрямую, если вам нужно другое поведение кэширования.

Относительно вашего исключениябез знания прецедента, точного исключения и его трассировки стека диагностировать сложно.

2 голосов
/ 17 августа 2011

Ответ JB - прямо на деньги.В дополнение к этому, вот как можно включить кэширование запросов для каждого запроса, а не глобально для всего шаблона:

public List findBySomething(final int something) {
    return getHibernateTemplate().execute(new HibernateCallback<List>() {
        @Override
        public List doInHibernate(Session session) {
            Query query = session.createQuery("from Something where something = :something");
            query.setParameter("something", something);
            query.setCacheable(true);
            return query.list();
        }
    });
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...