使用Hibernate的二级缓存:EhCache,但是不知道错在哪里?hibernate.cfg.xml
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration
    PUBLIC "-//Hibernate/Hibernate Configuration DTD//EN"
    "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd"><hibernate-configuration>
    <session-factory > <!-- local connection properties -->
<property name="connection.url">jdbc:mysql:///itcastbbs2</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<property name="connection.username">root</property>
<property name="connection.password">111111</property>
<!-- property name="connection.pool_size"></property -->        <property name="dialect">org.hibernate.dialect.MySQLDialect</property>        <property name="show_sql">false</property>
        <property name="hbm2ddl.auto">update</property> <property name="hibernate.cache.use_second_level_cache">true</property>
<property name="hibernate.cache.use_query_cache">true</property>
<property name="hibernate.cache.provider_class">org.hibernate.cache.EhCacheProvider</property>        <mapping resource="cn/itcast/bbs/domain/User.hbm.xml" />
    </session-factory>
</hibernate-configuration>

解决方案 »

  1.   

    ehcache.xml:
    <?xml version="1.0" encoding="UTF-8"?>
    <ehcache>
        <diskStore path="D:\job2\cache"/>
        <defaultCache maxElementsInMemory="10000"
            eternal="false"
            overflowToDisk="true"
            timeToIdleSeconds="120"
            timeToLiveSeconds="180"
            diskPersistent="false"
            diskExpiryThreadIntervalSeconds="60"/>
        <cache name="cn.itcast.bbs.domain.User"
            maxElementsInMemory="100" 
            eternal="false"
            overflowToDisk="true"
            timeToIdleSeconds="300"
            timeToLiveSeconds="600"
            diskPersistent="false"/>   
    </ehcache>User.hbm.xml<?xml version="1.0" encoding="utf-8"?>
    <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
    "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"><hibernate-mapping package="cn.itcast.bbs.domain">
    <class name="User" table="itcast_user">
      <cache usage="read-write" region="cn.itcast.bbs.domain.User"/>
    <id name="id" column="id" length="45">
    <generator class="uuid"/>
    </id>
    <property name="loginName" column="loginName" length="128" />
    <property name="password" column="password" length="128" />
            <property name="email" column="email" length="128"/>
    <property name="nickName" column="nickname" length="128"/>

    </class>



    </hibernate-mapping>
      

  2.   

     UserTest.java:测试代码
    import java.util.List;import javax.annotation.Resource;import org.hibernate.Session;
    import org.hibernate.SessionFactory;
    import org.hibernate.Transaction;
    import org.hibernate.cfg.Configuration;
    import org.junit.BeforeClass;
    import org.junit.Test;
    import org.springframework.beans.BeansException;
    import org.springframework.context.ApplicationContext;
    import org.springframework.context.support.ClassPathXmlApplicationContext;import cn.itcast.bbs.domain.User;
    import cn.itcast.bbs.service.UserService;public class UserTest { 
      private static UserService userService;

    @BeforeClass
    public static void setUpBeforeClass() throws Exception {
    try {
    ApplicationContext act=new ClassPathXmlApplicationContext("applicationContext.xml");
    userService=(UserService)act.getBean("userServiceImpl");
        //System.out.println("userService:"+userService);
    } catch (Exception e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    }

    @Test
    public void testSpring(){
    User user=userService.getUser("ff80808129e398d90129e398db620001");
            System.out.println("userLoginName:"+user.getLoginName()); 

     try {
     System.out.println("关闭数据库");
         Thread.sleep(1000*15);
    } catch (InterruptedException e) {
    // TODO Auto-generated catch block
    e.printStackTrace();
    }
    System.out.println("睡眠结束");
     
    user=userService.getUser("ff80808129e398d90129e398db620001");
        System.out.println("userLoginName:"+user.getLoginName()); 

    }

    }
      

  3.   

    打印结果是:
    userLoginName:asdf
    关闭数据库
    睡眠结束------------------------------说明,缓存中没有第一次查询的数据。
    怎样才能在缓存中有数据呢?
    或者哪里出了错误呢?
      

  4.   

    当线程睡眠时,我将mysql的服务停止了。
    结果在JUnit中报错:org.springframework.transaction.TransactionSystemException: Could not commit Hibernate transaction; nested exception is org.hibernate.TransactionException: JDBC commit failed
    at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:610)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:709)
    at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:678)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:321)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:116)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
    at $Proxy10.getUser(Unknown Source)
    at cn.test.UserTest.testSpring(UserTest.java:52)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:59)
    at org.junit.internal.runners.MethodRoadie.runTestMethod(MethodRoadie.java:98)
    at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:79)
    at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:87)
    at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:77)
    at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:42)
    at org.junit.internal.runners.JUnit4ClassRunner.invokeTestMethod(JUnit4ClassRunner.java:88)
    at org.junit.internal.runners.JUnit4ClassRunner.runMethods(JUnit4ClassRunner.java:51)
    at org.junit.internal.runners.JUnit4ClassRunner$1.run(JUnit4ClassRunner.java:44)
    at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:27)
    at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:37)
    at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:38)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
    Caused by: org.hibernate.TransactionException: JDBC commit failed
    at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:130)
    at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:606)
    ... 30 more
    Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLNonTransientConnectionException: Communications link failure during commit(). Transaction resolution unknown.
    at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
    at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:39)
    at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:27)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:513)
    at com.mysql.jdbc.Util.handleNewInstance(Util.java:406)
    at com.mysql.jdbc.Util.getInstance(Util.java:381)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:985)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:957)
    at com.mysql.jdbc.SQLError.createSQLException(SQLError.java:927)
    at com.mysql.jdbc.ConnectionImpl.commit(ConnectionImpl.java:1561)
    at org.hibernate.transaction.JDBCTransaction.commitAndResetAutoCommit(JDBCTransaction.java:139)
    at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:115)
    ... 31 more
      

  5.   

    说明Ehcache没起作用?
    错在哪里呢?向各位请教了。
      

  6.   

    hibernate调用了ehcache.xml在硬盘上生成了3个DATA文件,均为0k。
    为什么第一次查询的user,会没有缓存呢?
      

  7.   

       <cache name="cn.itcast.bbs.domain.User"
            maxElementsInMemory="100" 
            eternal="true"
            overflowToDisk="false"

            timeToIdleSeconds="300"
            timeToLiveSeconds="600"
            diskPersistent="false"/>   
    </ehcache>这样试试
      

  8.   


    <ehcache xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="../config/ehcache.xsd">
        <diskStore path="java.io.tmpdir"/>
        <defaultCache
                maxElementsInMemory="10000"
                eternal="false"
                timeToIdleSeconds="3600"
                timeToLiveSeconds="3600"
                overflowToDisk="true"
                maxElementsOnDisk="10000000"
                diskPersistent="false"
                diskExpiryThreadIntervalSeconds="120"
                memoryStoreEvictionPolicy="LRU"
                />
         <cache name="cn.itcast.bbs.domain.User"
                maxElementsInMemory="5000"
                eternal="true"
                overflowToDisk="false"
                />
    </ehcache>
    时间上面的设置你可以按照自己的定义,这样试试看行不行
      

  9.   

    会报如下错误:org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'userServiceImpl': Injection of resource fields failed; nested exception is org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in class path resource [applicationContext.xml]: Invocation of init method failed; nested exception is net.sf.ehcache.CacheException: Error configuring from file:/D:/job2/ItcastBBS2/build/classes/ehcache.xml. Initial cause was Error configuring from input stream. Initial cause was null:13: Element <defaultCache> does not allow attribute "maxElementsOnDisk".
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessAfterInstantiation(CommonAnnotationBeanPostProcessor.java:293)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.populateBean(AbstractAutowireCapableBeanFactory.java:957)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:470)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
    at java.security.AccessController.doPrivileged(Native Method)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:217)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:164)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:429)
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:729)
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:381)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:139)
    at org.springframework.context.support.ClassPathXmlApplicationContext.<init>(ClassPathXmlApplicationContext.java:83)
    at cn.test.UserTest.setUpBeforeClass(UserTest.java:29)
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
    at java.lang.reflect.Method.invoke(Method.java:597)
    at org.junit.internal.runners.ClassRoadie.runBefores(ClassRoadie.java:49)
    at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:36)
    at org.junit.internal.runners.JUnit4ClassRunner.run(JUnit4ClassRunner.java:42)
    at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:38)
    at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:460)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:673)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:386)
    at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:196)
    Caused by: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'sessionFactory' defined in class path resource [applicationContext.xml]: Invocation of init method failed; nested exception is net.sf.ehcache.CacheException: Error configuring from file:/D:/job2/ItcastBBS2/build/classes/ehcache.xml. Initial cause was Error configuring from input stream. Initial cause was null:13: Element <defaultCache> does not allow attribute "maxElementsOnDisk".
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1336)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:471)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory$1.run(AbstractAutowireCapableBeanFactory.java:409)
    at java.security.AccessController.doPrivileged(Native Method)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:380)
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:264)
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:217)
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:261)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:185)
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:168)
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.getResource(CommonAnnotationBeanPostProcessor.java:427)
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor$ResourceElement.getResourceToInject(CommonAnnotationBeanPostProcessor.java:502)
    at org.springframework.beans.factory.annotation.InjectionMetadata$InjectedElement.inject(InjectionMetadata.java:180)
    at org.springframework.beans.factory.annotation.InjectionMetadata.injectFields(InjectionMetadata.java:105)
    at org.springframework.context.annotation.CommonAnnotationBeanPostProcessor.postProcessAfterInstantiation(CommonAnnotationBeanPostProcessor.java:290)
    ... 29 more
    Caused by: net.sf.ehcache.CacheException: Error configuring from file:/D:/job2/ItcastBBS2/build/classes/ehcache.xml. Initial cause was Error configuring from input stream. Initial cause was null:13: Element <defaultCache> does not allow attribute "maxElementsOnDisk".
    at net.sf.ehcache.config.ConfigurationFactory.parseConfiguration(ConfigurationFactory.java:95)
    at net.sf.ehcache.config.ConfigurationFactory.parseConfiguration(ConfigurationFactory.java:131)
    at net.sf.ehcache.CacheManager.parseConfiguration(CacheManager.java:241)
    at net.sf.ehcache.CacheManager.init(CacheManager.java:190)
    at net.sf.ehcache.CacheManager.<init>(CacheManager.java:183)
    at org.hibernate.cache.EhCacheProvider.start(EhCacheProvider.java:124)
    at org.hibernate.impl.SessionFactoryImpl.<init>(SessionFactoryImpl.java:183)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1300)
    at org.springframework.orm.hibernate3.LocalSessionFactoryBean.newSessionFactory(LocalSessionFactoryBean.java:816)
    at org.springframework.orm.hibernate3.LocalSessionFactoryBean.buildSessionFactory(LocalSessionFactoryBean.java:734)
    at org.springframework.orm.hibernate3.AbstractSessionFactoryBean.afterPropertiesSet(AbstractSessionFactoryBean.java:211)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.invokeInitMethods(AbstractAutowireCapableBeanFactory.java:1367)
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.initializeBean(AbstractAutowireCapableBeanFactory.java:1333)
    ... 43 more
      

  10.   

    首先表示谢意。
    问题找到了是在UserServiceImpl.java的public User getUser(String id)上面没有写:
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    为什么会是这样的?它怎么会影响二级缓存呢?UserServiceImpl.java:
    package cn.itcast.bbs.service.impl;import java.util.List;import javax.annotation.Resource;import org.hibernate.SessionFactory;
    import org.springframework.stereotype.Service;
    import org.springframework.transaction.annotation.Propagation;
    import org.springframework.transaction.annotation.Transactional;import cn.itcast.bbs.domain.User;import cn.itcast.bbs.service.UserService;@Service("userServiceImpl")
    @Transactional
    public class UserServiceImpl implements UserService{ @Resource SessionFactory sessionFactory;

    @Override
    @Transactional(propagation = Propagation.NOT_SUPPORTED, readOnly = true)
    public User getUser(String id) {
    return (User)sessionFactory.getCurrentSession().get(User.class,id);
    }
    }
      

  11.   

    还有个问题:我将ehcache.xml删除了,保留了User.hbm.xml中的 <cache usage="read-write" region="cn.itcast.bbs.domain.User"/>
    依然可以是使用二级缓存?那ehcache.xml文件,可以不用存在吗?
      

  12.   



    你的这两个问题好奇怪!!!!!!!!!!!!!!!!!!!

    第一个与spring管理有关系。

    第二个,可能使用了jar包的默认配置。
      

  13.   

    你程序中真的用ehcache了吗?如果用到了ehcache组件的相关方法,而没有ehcache.xml配置的话,是不可能的啊
      

  14.   

    hibernate本身有一级缓存,基于session
      

  15.   

    对呀,如果将ehcache-1.2.3.jar去掉,程序无法运行。如果将<class name="User" table="itcast_user">去掉,那么程序运行的结果是:
    userLoginName:asdf
    关闭数据库
    睡眠结束
    没有缓存内容。
      

  16.   

    这个是因为你在查询的时候没有显示的表明使用查询缓存,你使用了二级缓存同时也打开了查询缓存,但是只是在配置文件   <property name="hibernate.cache.use_query_cache">true</property>
    这样声明打开查询缓存还没有用,在查询的时候还必须设值
      user=userService.getUser("ff80808129e398d90129e398db620001");
    你这个是根据条件查询user所以我猜想你的getUser方法只是这样的
    Query query=session.createQuery("***");
    如果我猜的没错的话,应该只有上面一句,如果真是这样,是不行的,还必须这样设置,显示地让Query查询的时候使用查询缓存:
    query.setCacheable(true);
    如果我没猜错的话,你的问题应该出在这里
      

  17.   

    Ehcache和OsCache的配置文件是可以省略的,如果没有缓存配置文件,hibernate会使用这两个缓存的默认配置.