Спящий второй уровень
Я пытаюсь заставить работать кеш второго уровня, используя реализацию ehcache.
Я уверен, что это какая-то очевидная ошибка, которую я совершаю, но я не понимаю, что это!
Чтобы проверить мой кеш, я делаю следующее:
Создание объекта и сохранение его. Я "получаю" его один раз в транзакции, и вижу, что я получаю объект обратно без попадания в db, а это всего лишь спящий режим кэш-памяти первого уровня, который делает свое дело.
Затем я фиксирую транзакцию и начинаю новый сеанс.
На этот раз, когда я "получаю" объект, я могу увидеть отсутствие кеша в ehcache в отладках. Я ожидал бы, что объект будет в кеше сейчас, так как я сохранил его в предыдущей транзакции?
Вот мой код:
Session session = getSession();
session.beginTransaction();
Test1 test1a = new Test1();
test1a.setId(5);
test1a.setName("Test 1");
test1a.setValue(10);
// Touch it
session.save(test1a);
// Now get it
Test1 test1b = (Test1)session.get(Test1.class, 5);
// Within a transaction, the session caches it - no db hit
System.out.println("GOT object with value "+test1b.getValue());
session.getTransaction().commit();
System.out.println("Between sessions");
session = getSession();
session.beginTransaction();
test1b = (Test1)session.get(Test1.class, 5);
System.out.println("GOT object with value "+test1b.getValue());
session.getTransaction().commit();
А вот соответствующая часть моего hibernate.cfg.xml
<property name="cache.provider_class">org.hibernate.cache.EhCacheProvider</property>
И мой ehcache.xml
<?xml version="1.0" encoding="UTF-8"?>
<ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://ehcache.sf.net/ehcache.xsd">
<cache name="com.play.hibernate1.Test1" maxElementsInMemory="1000" eternal="false" timeToLiveSeconds="600" overflowToDisk="false"/>
<defaultCache maxElementsInMemory="10000" eternal="false"
overflowToDisk="true" timeToIdleSeconds="10" timeToLiveSeconds="20" diskPersistent="true" />
</ehcache>
И мои аннотации
@Entity
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITE)
public class Test1 {
И журналы отладки
11:21:03,474 DEBUG CacheManager:239 - Настройка ehcache из пути к классам. 11:21:03,479 Фабрика конфигурации DEBUG: 122 - Конфигурация ehcache из ehcache.xml, найденного в пути к классам: file: /Users/bw/Documents/workspace/hibernate1/target/classes/ehcache.xml 11: 21: 03,479 Фабрика конфигурации DEBUG: 87 - Настройка ehcache из URL: file: /Users/brucewood/Documents/workspace/hibernate1/target/classes/ehcache.xml 11: 21: 03,480 DEBUG ConfigurationFactory:139 - Настройка ehcache из InputStream 11:21:03,485 DEBUG BeanHandler:213 - Игнорирование атрибута ehcache xmlns:xsi 11:21:03,485 DEBUG BeanHandler:213 - Игнорирование атрибута ehcache xsi:noNamespaceSchemaLocation 11:21:03,517 DEBUG ConfigurationHelper:208 - Класс CacheManagerEventListenerFactory не указан. Пропуск... 11:21:03,518 DEBUG ConfigurationHelper:183 - Не указана CachePeerListenerFactoryConfiguration. Не настраивается CacheManagerPeerListener. 11:21:03,518 DEBUG ConfigurationHelper:159 - Конфигурация CachePeerProviderFactoryConfiguration не указана. Не настраивается CacheManagerPeerProvider. 11:21:03,525 DEBUG ConfigurationHelper:135 - не указан класс BootstrapCacheLoaderFactory. Пропуск... 11:21:03,526 DEBUG ConfigurationHelper:135 - Не указан класс BootstrapCacheLoaderFactory. Пропуск... 11:21:03,532 DEBUG MemoryStore:73 - Инициализированный net.sf.ehcache.store.LruMemoryStore для com.play.hibernate1.Test1 11:21:03,533 DEBUG LruMemoryStore:71 - com.play.hibernate1.Test1 Cache: Использование реализации SpoolingLinkedHashMap 11: 21: 03,533 Кэш-память отладки:429 - Инициализированный кэш: com.play.hibernate1.Test1 1528 [Finalizer] INFO org.hibernate.connection.DriverManagerConnectionProvider - очистка пула соединений: jdbc:mysql://localhost:3306/play 1668 [main] INFO org.hibernate.impl.SessionFactoryObjectFactory - Не привязывать фабрику к JNDI, имя JNDI не настроено, объект GOT со значением 10 Hibernate: /* вставить com.play.hibernate1.Test1 */ вставить в Test1 (имя, значение, id) значения (?,?,?) 1274984463818|1|1|batch|/* вставить com.play.hibernate1.Test1 */ вставить в Test1 (имя, значение, id) значения (?,?,?)|/* вставить com.play.hibernate1.Test1 */ вставить в значения Test1 (имя, значение, id) ("Тест 1", 10, 5) 1274984463820|1|1| оператор | / * вставить com.play.hibernate1.Test1 */ insert into Test1 (имя, значение, идентификатор) значения (?,?,?)|/* вставить com.play.hibernate1.Test1 */ вставить в Test1 (имя, значение, идентификатор) значения ('Test 1', 10, 5) 1274984463821|1|1|commit|| Между сессиями 11:21:03,823 Отладка EhCache:68 - ключ: com.play.hibernate1.Test1#5 11:21:03,823 Отладка Память хранилища:138 - com.play.hibernate1.Test1Cache: com.play.hibernate1.Test1MemoryStore промах для com.play.hibernate1.Test1 # 5 11:21:03,823 Кэш отладки:661 - кэш com.play.hibernate1.Test1 - Мисс 11:21:03,824 EhCache отладки:77 - Элемент для com.play.hibernate1.Test1 # 5 имеет значение Hibernate: / * загрузить com.play.hibernate1.Test1 */ выберите test1x0_.id в качестве id0_0_, test1x0_.name в качестве name0_0_, test1x0_.value в качестве value0_0_ из Test1 test1x0_, где test1x0_.id=? 1274984463829|4|1| оператор | / * загрузить com.play.hibernate1.Test1 */ выбрать test1x0_.id в качестве id0_0_, test1x0_.name в качестве имени0_0_, test1x0_.value в качестве значения0_0_ из Test1 test1x0_, где test1x0_.id=?|/* загрузите com.play.hibernate1.Test1 */ выберите test1x0_.id в качестве id0_0_, test1x0_.name в качестве имени0_0_, test1x0_.value в качестве значения0_0_ из Test1 test1x0_, где test1x0_.id=5 1274984463831|-1||resultset|/* загрузить com. play.hibernate1.Test1 * / выберите test1x0_.id в качестве id0_0_, test1x0_.name в качестве имени0_0_, test1x0_.value в качестве value0_0_ из Test1 test1x0_, где test1x0_.id=5|name0_0_ = тест 1, value0_0_ = 10 GOT-объекта со значением 10498 |0|1| совершить ||
Спасибо за вашу помощь!
2 ответа
Проблема была в том, что я использовал NONSTRICT_READ_WRITE. Похоже, это соответствует требованиям из этого объяснения в документах:
Если приложению требуется лишь время от времени обновлять данные (т. Е. Крайне маловероятно, что две транзакции попытаются обновить один и тот же элемент одновременно), и строгая изоляция транзакций не требуется, может быть уместен кэш без ограничения на чтение и запись. Если кеш используется в среде JTA, вы должны указать hibernate.transaction.manager_lookup_class. В других средах вы должны убедиться, что транзакция завершена при вызове Session.close() или Session.disconnect().
но на самом деле похоже, что он не добавляет сохраненные объекты в кеш... Документы здесь немного тонкие, ИМО. В Hibernate лучше использовать параметры кэширования в Java Persistence, хотя пока немного поясняем, что именно происходит с вашими данными. Тем не мение..
Я изменил свой параметр кэширования на READ_WRITE, и теперь он работает как положено.
Также обратите внимание, что при первом добавлении объекта в кеш вы получаете "промах кеша" в отладках ehcache. Предположительно, он смотрит в свой кеш, находит, что объекта там нет, записывает промах, затем добавляет объект. После этого вы получаете "хиты".
Также будьте осторожны с ошибкой в org.hibernate.action.internal.BulkOperationCleanupAction.# DisabledEntity смотрите обсуждение в обоих
https://forum.hibernate.org/viewtopic.php?f=1&t=998970
а также