Кэширование сущностей/запросов Hibernate Infinispan


Я несколько дней бился головой о стену с этой проблемой.

Мы пытаемся реализовать кэш второго уровня Hibernate, используя Infinispan. Приложение работает на JBoss AS 6 и использует транзакции JTA.

В нашем файле persistence.xml у нас есть:

...
<!-- JTA configurations -->
<property name="hibernate.transaction.manager_lookup_class" value="org.hibernate.transaction.JBossTransactionManagerLookup" />
<property name="current_session_context_class" value="jta" />

<!-- Infinispan configurations -->
<property name="hibernate.cache.use_second_level_cache" value="true" />
<property name="hibernate.cache.use_query_cache" value="true" />

<property name="hibernate.cache.region.factory_class" value="org.hibernate.cache.infinispan.InfinispanRegionFactory"/>
<property name="hibernate.cache.infinispan.cachemanager" value="java:CacheManager/entity"/>
...

как определено здесь:< /а>

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

Первый вариант использования: у нас есть записи в базе данных, которые будут содержать справочные данные. Эти данные не будут изменяться в течение длительного периода времени (мы надеемся :) ).

Мы хотим кэшировать эти записи, так как они, вероятно, будут часто запрашиваться. И когда пользователи запрашивают эти данные, им не нужно будет обращаться к БД, так как они должны кэшироваться.

В данном случае это кеш запроса типа кеша или кеш сущностей? Поскольку запрос всегда один и тот же, я понимаю, что кеш запросов, поскольку запрос que, должен всегда возвращать одни и те же результаты.

Мой запрос:

List<MyEntity> list = session.createCriteria(MyEntity.class)
        .add(Restrictions.eq("id", 1))
        .setCacheable(true)
        .list();

Сценарий 2. Пользователь получает определенную запись из БД и может ее обновить. Мы хотели бы, чтобы эта сущность (или список сущностей) сохранялась в кэше сеанса пользователя (сеанса входа), поэтому, если он обновит эту сущность на клиенте, нам не нужно будет делать выбор перед обновлением. В этом случае, поскольку мы сохраняем определенные сущности, это считается кэшированием сущностей, верно? Если мы хотим сохранить

Для этого мы используем:

@Cacheable (true)
@Cache(usage = CacheConcurrencyStrategy.TRANSACTIONAL)
public class MyEntity implements Serializable 
{
...
}

Правильно ли я делаю эти предположения? Если нет, то какой здесь подход? Думаю, я делаю из этого большой беспорядок.


person Nuno Gonçalves    schedule 31.07.2012    source источник


Ответы (2)


Перекрестная публикация на https://community.jboss.org/message/751275#751275 - посмотри мои ответы там.

person Galder Zamarreño    schedule 20.08.2012

Кэш 2-го уровня (сущности) представляет собой (что упрощает) карту, основанную на идентификаторе в качестве ключа. Таким образом, каждый раз, когда эталонные данные «ссылаются» на другой объект, диспетчер объектов сначала проверяет, присутствуют ли они в кеше, прежде чем переходить к БД.

Кэш запросов — это кеш объектов результатов (идентификаторов) запроса. Затем на основе идентификаторов он извлечет соответствующий объект (предпочтительно из кеша объектов...), поэтому вам нужно, чтобы объект был кэширован в кеше 2-го уровня, чтобы быть полезным.

Для вашего первого варианта использования справочные данные: вы должны аннотировать объект как кэшируемый и использовать стратегию только для чтения. Менеджер сущностей поместит эталонные данные в объект ссылки при загрузке или использует find(clazz,id) для получения эталонных данных из кэша 2-го уровня.

Случай 2 немного сложнее. Кэш с областью действия «сессии» отсутствует (вам нужно управлять им самостоятельно через SFSB или любой механизм сеанса верхнего уровня, если вам нужно сохранить промежуточный результат, привязанный к сеансу пользователя). Если вы сделаете объект кэшируемым, он будет кэшироваться для каждого пользователя на сервере, контекст менеджера объектов не имеет прямой связи с пользователем.

Если вы хотите предотвратить выбор перед обновлением, вы должны запретить объекту переходить в неуправляемое состояние (чтобы предотвратить слияние) через расширенный контекст сохраняемости. Если объект может часто обновляться несколькими пользователями, кеш может снизить производительность, так как для управления согласованностью потребуется больше времени, чем потребуется для обращения к БД.

Если у вас есть узкое место в производительности, вы должны сначала посмотреть на связанную аннотацию выборки и распространения объекта, если они слишком велики, вы делаете запрос и/или обновляете слишком много данных из и в БД.

person Kazaag    schedule 31.07.2012
comment
Я все еще пытаюсь усвоить весь ваш ответ. И у меня есть еще один вопрос. Что произойдет в моем первом случае использования, если я добавлю еще один объект эталонных данных (запись) в БД (используя то же приложение)? Будет ли кеш знать, что результат запроса был изменен, и в следующий раз, когда будет сделан выбор, он попадет в БД? - person Nuno Gonçalves; 31.07.2012
comment
Я не знаю, поместит ли он его в кеш, когда сохранит его. Вероятно, он сделает выбор, так как могут быть некоторые изменения данных из-за триггеров. В любом случае он сделает максимум один выбор, а затем поместит его в кеш. - person Kazaag; 01.08.2012
comment
Вы можете найти более подробную информацию в этом сообщении: javalobby.org/java/forums/t48846.html - person Kazaag; 01.08.2012