我正在尝试使用 ehcache 实现使二级 hibernate 缓存工作。
我确定这是我犯的一些明显的菜鸟错误,但我看不出它是什么!
为了测试我的缓存,我正在执行以下操作:
创建一个对象并保存它。我在事务中“获取”了一次,在那里我可以看到我在没有数据库命中的情况下取回了对象,这只是 hibernate 一级缓存在做它的事情。
然后我提交事务并开始一个新 session 。
这一次,当我“获取”对象时,我可以在调试中看到来自 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 - Configuring ehcache from classpath. 11:21:03,479 DEBUG ConfigurationFactory:122 - Configuring ehcache from ehcache.xml found in the classpath: file:/Users/bw/Documents/workspace/hibernate1/target/classes/ehcache.xml 11:21:03,479 DEBUG ConfigurationFactory:87 - Configuring ehcache from URL: file:/Users/brucewood/Documents/workspace/hibernate1/target/classes/ehcache.xml 11:21:03,480 DEBUG ConfigurationFactory:139 - Configuring ehcache from InputStream 11:21:03,485 DEBUG BeanHandler:213 - Ignoring ehcache attribute xmlns:xsi 11:21:03,485 DEBUG BeanHandler:213 - Ignoring ehcache attribute xsi:noNamespaceSchemaLocation 11:21:03,517 DEBUG ConfigurationHelper:208 - No CacheManagerEventListenerFactory class specified. Skipping... 11:21:03,518 DEBUG ConfigurationHelper:183 - No CachePeerListenerFactoryConfiguration specified. Not configuring a CacheManagerPeerListener. 11:21:03,518 DEBUG ConfigurationHelper:159 - No CachePeerProviderFactoryConfiguration specified. Not configuring a CacheManagerPeerProvider. 11:21:03,525 DEBUG ConfigurationHelper:135 - No BootstrapCacheLoaderFactory class specified. Skipping... 11:21:03,526 DEBUG ConfigurationHelper:135 - No BootstrapCacheLoaderFactory class specified. Skipping... 11:21:03,532 DEBUG MemoryStore:73 - Initialized net.sf.ehcache.store.LruMemoryStore for com.play.hibernate1.Test1 11:21:03,533 DEBUG LruMemoryStore:71 - com.play.hibernate1.Test1 Cache: Using SpoolingLinkedHashMap implementation 11:21:03,533 DEBUG Cache:429 - Initialised cache: com.play.hibernate1.Test1 1528 [Finalizer] INFO org.hibernate.connection.DriverManagerConnectionProvider - cleaning up connection pool: jdbc:mysql://localhost:3306/play 1668 [main] INFO org.hibernate.impl.SessionFactoryObjectFactory - Not binding factory to JNDI, no JNDI name configured GOT object with value 10 Hibernate: /* insert com.play.hibernate1.Test1 */ insert into Test1 (name, value, id) values (?, ?, ?) 1274984463818|1|1|batch|/* insert com.play.hibernate1.Test1 */ insert into Test1 (name, value, id) values (?, ?, ?)|/* insert com.play.hibernate1.Test1 */ insert into Test1 (name, value, id) values ('Test 1', 10, 5) 1274984463820|1|1|statement|/* insert com.play.hibernate1.Test1 */ insert into Test1 (name, value, id) values (?, ?, ?)|/* insert com.play.hibernate1.Test1 */ insert into Test1 (name, value, id) values ('Test 1', 10, 5) 1274984463821|1|1|commit|| Between sessions 11:21:03,823 DEBUG EhCache:68 - key: com.play.hibernate1.Test1#5 11:21:03,823 DEBUG MemoryStore:138 - com.play.hibernate1.Test1Cache: com.play.hibernate1.Test1MemoryStore miss for com.play.hibernate1.Test1#5 11:21:03,823 DEBUG Cache:661 - com.play.hibernate1.Test1 cache - Miss 11:21:03,824 DEBUG EhCache:77 - Element for com.play.hibernate1.Test1#5 is null Hibernate: /* load com.play.hibernate1.Test1 */ select test1x0_.id as id0_0_, test1x0_.name as name0_0_, test1x0_.value as value0_0_ from Test1 test1x0_ where test1x0_.id=? 1274984463829|4|1|statement|/* load com.play.hibernate1.Test1 */ select test1x0_.id as id0_0_, test1x0_.name as name0_0_, test1x0_.value as value0_0_ from Test1 test1x0_ where test1x0_.id=?|/* load com.play.hibernate1.Test1 */ select test1x0_.id as id0_0_, test1x0_.name as name0_0_, test1x0_.value as value0_0_ from Test1 test1x0_ where test1x0_.id=5 1274984463831|-1||resultset|/* load com.play.hibernate1.Test1 */ select test1x0_.id as id0_0_, test1x0_.name as name0_0_, test1x0_.value as value0_0_ from Test1 test1x0_ where test1x0_.id=5|name0_0_ = Test 1, value0_0_ = 10 GOT object with value 10 1274984463834|0|1|commit||
感谢您的帮助!
最佳答案
问题是我使用的是 NONSTRICT_READ_WRITE。它似乎符合文档中此解释的要求:
If the application only occasionally needs to update data (i.e. if it is extremely unlikely that two transactions would try to update the same item simultaneously), and strict transaction isolation is not required, a nonstrict-read-write cache might be appropriate. If the cache is used in a JTA environment, you must specify hibernate.transaction.manager_lookup_class. In other environments, you should ensure that the transaction is completed when Session.close() or Session.disconnect() is called.
但实际上它看起来并没有将保存的对象添加到缓存中.. IMO,这里的文档有点薄。在 Java Persistence with Hibernate 中对缓存选项有更好的处理,尽管在对数据实际发生的事情的具体解释上仍然有点薄弱。无论如何..
我将缓存选项更改为 READ_WRITE,现在它按预期工作。
另请注意,第一次将对象添加到缓存中时,您会在 ehcache 调试中看到“缓存未命中”。据推测,它在其缓存中查找,发现该对象不存在,记录未命中,然后添加该对象。之后,您会获得“命中”。
关于java - hibernate 二级 ehcache 未命中,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2923775/