Hibernate 设置休眠二级缓存
我对hibernate和spring是新手,我尝试使用hibernate二级缓存。但它似乎不起作用。我有以下的测试课程:Hibernate 设置休眠二级缓存,hibernate,spring,second-level-cache,Hibernate,Spring,Second Level Cache,我对hibernate和spring是新手,我尝试使用hibernate二级缓存。但它似乎不起作用。我有以下的测试课程: @RunWith(SpringJUnit4ClassRunner.class) @ContextConfiguration(locations = { "classpath:applicationContext.xml" }) @TransactionConfiguration @Transactional public class CacheTest extends Abs
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext.xml" })
@TransactionConfiguration
@Transactional
public class CacheTest extends AbstractTransactionalJUnit4SpringContextTests
{
@Test
public void testCache1()
{
System.out.println("Running testCache1");
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
MutableDAO<AppUser> appUserDAO = new MutableDAOImpl<AppUser>(AppUser.class, (SessionFactory) ctx.getBean("OnMediaSessionFactory"), 10);
assertNotNull("AppUser DAO is null.", appUserDAO);
SessionFactory sessionFactory = (SessionFactory)ctx.getBean("OnMediaSessionFactory");
long numberOfUsers = appUserDAO.countAll();
System.out.println("Number of rows :" + numberOfUsers);
final String cacheRegion = AppUser.class.getCanonicalName();
SecondLevelCacheStatistics settingsStatistics = sessionFactory.getStatistics().
getSecondLevelCacheStatistics(cacheRegion);
StopWatch stopWatch = new StopWatch();
stopWatch.start();
appUserDAO.findAll();
stopWatch.stop();
System.out.println("Query time : " + stopWatch.getTotalTimeSeconds());
System.out.println(settingsStatistics);
}
@Test
public void testCache2()
{
System.out.println("Running testCache2");
ApplicationContext ctx = new ClassPathXmlApplicationContext("applicationContext.xml");
MutableDAO<AppUser> appUserDAO = new MutableDAOImpl<AppUser>(AppUser.class, (SessionFactory) ctx.getBean("OnMediaSessionFactory"), 10);
assertNotNull("AppUser DAO is null.", appUserDAO);
SessionFactory sessionFactory = (SessionFactory)ctx.getBean("OnMediaSessionFactory");
long numberOfUsers = appUserDAO.countAll();
System.out.println("Number of rows :" + numberOfUsers);
final String cacheRegion = AppUser.class.getCanonicalName();
SecondLevelCacheStatistics settingsStatistics = sessionFactory.getStatistics().
getSecondLevelCacheStatistics(cacheRegion);
StopWatch stopWatch = new StopWatch();
stopWatch.start();
appUserDAO.findAll();
stopWatch.stop();
System.out.println("Query time : " + stopWatch.getTotalTimeSeconds());
System.out.println(settingsStatistics);
}
}
要让它工作,我必须做些什么?您的测试看起来很奇怪,您为每个测试创建了一个新的应用程序上下文,因此Hibernate
SessionFactory
在测试之间以及它的二级缓存都无法存活
正确的测试如下所示:
Running testCache1
Number of rows :81
Query time : 0.129
SecondLevelCacheStatistics[hitCount=0,missCount=0,putCount=81,elementCountInMemory=81,elementCountOnDisk=0,sizeInMemory=219634]
Running testCache2
Number of rows :81
Query time : 0.063
SecondLevelCacheStatistics[hitCount=0,missCount=0,putCount=81,elementCountInMemory=81,elementCountOnDisk=0,sizeInMemory=219634]
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext.xml" })
public class CacheTest extends AbstractTransactionalJUnit4SpringContextTests
{
@Autowired
private MutableDAO<AppUser> appUserDAO;
@Autowired
private SessionFactory sessionFactory;
private TransactionTemplate tx;
@Autowired
public void setPtm(PlatformTransactionManagement ptm) {
tx = new TransactionTemplate(ptm);
}
@Test
public void doTestCache() {
// Using programmatic transaction management since we need 2 transactions
// inside the same method
// 1st attempt
tx.execute(new TransactionCallbackWithoutResult() {
public void doInTransactionWithoutResult(TransactionStatus status) {
testCache();
}
});
// 2nd attempt
tx.execute(new TransactionCallbackWithoutResult() {
public void doInTransactionWithoutResult(TransactionStatus status) {
testCache();
}
});
}
public void testCache() {
long numberOfUsers = appUserDAO.countAll();
System.out.println("Number of rows :" + numberOfUsers);
final String cacheRegion = AppUser.class.getCanonicalName();
SecondLevelCacheStatistics settingsStatistics = sessionFactory.getStatistics().
getSecondLevelCacheStatistics(cacheRegion);
StopWatch stopWatch = new StopWatch();
stopWatch.start();
appUserDAO.findAll();
stopWatch.stop();
System.out.println("Query time : " + stopWatch.getTotalTimeSeconds());
System.out.println(settingsStatistics);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
<diskStore path="./cache" />
<defaultCache maxElementsInMemory="10000"
eternal="true"
overflowToDisk="true"
diskPersistent="true"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="FIFO" />
<cache name="com.mycompany.jpa.MyEntity"
maxElementsInMemory="50"
overflowToDisk="true" />
<cache name="org.hibernate.cache.StandardQueryCache"
maxElementsInMemory="50"
overflowToDisk="true" />
<cache name="org.hibernate.cache.UpdateTimestampsCache"
maxElementsInMemory="5000"
overflowToDisk="true" />
</ehcache>
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(位置={“classpath:applicationContext.xml”})
公共类CacheTest扩展了AbstractTransactionalJUnit4SpringContextTests
{
@自动连线
私有可变dao-appUserDAO;
@自动连线
私人会话工厂会话工厂;
私人交易模板;
@自动连线
公共作废setPtm(平台交易管理ptm){
tx=新交易模板(ptm);
}
@试验
公共void doTestCache(){
//使用编程事务管理,因为我们需要2个事务
//用同样的方法
//第一次尝试
tx.execute(新建TransactionCallbackWithoutResult(){
public void doInTransactionWithoutResult(交易状态){
testCache();
}
});
//第二次尝试
tx.execute(新建TransactionCallbackWithoutResult(){
public void doInTransactionWithoutResult(交易状态){
testCache();
}
});
}
公共void testCache(){
long numberOfUsers=appUserDAO.countAll();
System.out.println(“行数:”+numberOfUsers);
最终字符串cacheRegion=AppUser.class.getCanonicalName();
SecondLevelCacheStatistics settingsStatistics=sessionFactory.getStatistics()。
getSecondLevelCacheStatistics(cacheRegion);
秒表秒表=新秒表();
秒表。开始();
appUserDAO.findAll();
秒表;
System.out.println(“查询时间:+stopWatch.getTotalTimeSeconds());
系统输出打印LN(设置统计);
}
}
首先,请记住Hibernate默认情况下不使用任何缓存提供程序。因此,对于Hibernate的2L缓存,您需要一个“外部”缓存提供程序。对于我的答案,我将使用ehcache和hibernate3.3。请注意,配置在更新版本的Hibernate中已更改,因此,请阅读文档以了解您正在使用的确切版本
在Hibernate配置中,您遗漏了一个部分,即将Hibernate指向实际的提供者。属性hibernate.cache.provider\u类为hibernate 3.3执行此操作。将其值设置为net.sf.ehcache.hibernate.SingletonEhCacheProvider
现在,您还需要一个ehcache.xml,如下所示:
Running testCache1
Number of rows :81
Query time : 0.129
SecondLevelCacheStatistics[hitCount=0,missCount=0,putCount=81,elementCountInMemory=81,elementCountOnDisk=0,sizeInMemory=219634]
Running testCache2
Number of rows :81
Query time : 0.063
SecondLevelCacheStatistics[hitCount=0,missCount=0,putCount=81,elementCountInMemory=81,elementCountOnDisk=0,sizeInMemory=219634]
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations = { "classpath:applicationContext.xml" })
public class CacheTest extends AbstractTransactionalJUnit4SpringContextTests
{
@Autowired
private MutableDAO<AppUser> appUserDAO;
@Autowired
private SessionFactory sessionFactory;
private TransactionTemplate tx;
@Autowired
public void setPtm(PlatformTransactionManagement ptm) {
tx = new TransactionTemplate(ptm);
}
@Test
public void doTestCache() {
// Using programmatic transaction management since we need 2 transactions
// inside the same method
// 1st attempt
tx.execute(new TransactionCallbackWithoutResult() {
public void doInTransactionWithoutResult(TransactionStatus status) {
testCache();
}
});
// 2nd attempt
tx.execute(new TransactionCallbackWithoutResult() {
public void doInTransactionWithoutResult(TransactionStatus status) {
testCache();
}
});
}
public void testCache() {
long numberOfUsers = appUserDAO.countAll();
System.out.println("Number of rows :" + numberOfUsers);
final String cacheRegion = AppUser.class.getCanonicalName();
SecondLevelCacheStatistics settingsStatistics = sessionFactory.getStatistics().
getSecondLevelCacheStatistics(cacheRegion);
StopWatch stopWatch = new StopWatch();
stopWatch.start();
appUserDAO.findAll();
stopWatch.stop();
System.out.println("Query time : " + stopWatch.getTotalTimeSeconds());
System.out.println(settingsStatistics);
}
}
<?xml version="1.0" encoding="UTF-8"?>
<ehcache>
<diskStore path="./cache" />
<defaultCache maxElementsInMemory="10000"
eternal="true"
overflowToDisk="true"
diskPersistent="true"
diskExpiryThreadIntervalSeconds="120"
memoryStoreEvictionPolicy="FIFO" />
<cache name="com.mycompany.jpa.MyEntity"
maxElementsInMemory="50"
overflowToDisk="true" />
<cache name="org.hibernate.cache.StandardQueryCache"
maxElementsInMemory="50"
overflowToDisk="true" />
<cache name="org.hibernate.cache.UpdateTimestampsCache"
maxElementsInMemory="5000"
overflowToDisk="true" />
</ehcache>
你没有展示你的刀,所以,我不确定它是否正确。请注意,您始终需要明确说明缓存,因为它是用于特定位置的解决方案,而不是用于所有内容的通用解决方案。这意味着,在DAO中,您将添加一个查询提示,说明您的查询是可缓存的(从测试来看,您似乎需要查询缓存,而不仅仅是实体缓存)
如果您仍然无法使其工作,请参阅以下JIRA中的附件。它包含一个启用缓存的maven项目,因此,您可以将其与代码进行比较:
实体类本身必须显式可缓存-您这样做了吗?是的,我有@Cache(usage=cacheconcurrentystrategy.READ\u WRITE)谢谢您的回答。但是什么是@Autowired public void setPtm(PlatformTransactionManagement ptm){tx=new TransactionTemplate(ptm);}以及在特定的PlatformTransactionManagement中?@Daniel:编程事务管理需要它,请参阅。由于您希望检查缓存值在事务之间是否存在,因此需要在测试方法内执行多个事务,编程事务管理是一种很好的安排方式。我执行了您的代码,但现在我得到了行数:81查询时间:0.142 SecondLevelCacheStatistics[hitCount=0,missCount=0,putCount=0,elementCountInMemory=0,elementCountOnDisk=0,sizeInMemory=0]行数:81查询时间:0.031秒级缓存统计[hitCount=0,missCount=0,putCount=0,elementCountInMemory=0,elementCountOnDisk=0,sizeInMemory=0]@丹尼尔:如果缓存配置正确,加载单个实体时应该可以正常工作。但是,findAll()
似乎正在执行一个查询,所以您需要为该查询启用查询缓存的使用,@axtavt I将findAll()改为AppUser aUser=(AppUser)sessionFactory.getCurrentSession().load(AppUser.class,13351L)现在我得到:行数:81查询时间:0.0 SecondLevelCacheStatistics[hitCount=0,missCount=2,putCount=4,elementCountInMemory=4,elementCountOnDisk=0,sizeInMemory=10816]行数:81查询时间:0.0 SecondLevelCacheStatistics[hitCount=0,missCount=2,putCount=4,elementCountInMemory=4,elementCountOnDisk=0,sizeInMemory=10816]但我还是得到了命中率=0