在我解决完上一个问题以后,立刻又出现了新的问题,错误以下:html
org.springframework.dao.InvalidDataAccessApiUsageException: Write operations are not allowed in read-only mode (FlushMode.MANUAL): Turn your Session into FlushMode.COMMIT/AUTO or remove 'readOnly' marker from transaction definition. at org.springframework.orm.hibernate5.HibernateTemplate.checkWriteOperationAllowed(HibernateTemplate.java:1080) at org.springframework.orm.hibernate5.HibernateTemplate.lambda$save$11(HibernateTemplate.java:635) at org.springframework.orm.hibernate5.HibernateTemplate.doExecute(HibernateTemplate.java:381) at org.springframework.orm.hibernate5.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:347) at org.springframework.orm.hibernate5.HibernateTemplate.save(HibernateTemplate.java:634) at com.spring.oa.dao.impl.PersonDaoImpl.savePerson(PersonDaoImpl.java:11) at com.spring.oa.service.impl.PersonServiceImpl.savePerson(PersonServiceImpl.java:20) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497) at org.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:338) at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:197) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:163) at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:294) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:98) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:185) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:212) at com.sun.proxy.$Proxy34.savePerson(Unknown Source) at spring.oa.test.PersonTest.testSavePerson(PersonTest.java:14) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:497) at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45) at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42) at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:28) at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68) at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47) at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231) at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60) at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229) at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50) at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222) at org.junit.runners.ParentRunner.run(ParentRunner.java:300) at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86) at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382) at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
错误的缘由说的很清楚:只读模式下(FlushMode.NEVER/MANUAL)写操做不被容许:把你的Session改为FlushMode.COMMIT/AUTO或者清除事务定义中的readOnly标记。java
下面是错误代码:spring
<tx:advice transaction-manager="transactionManager" id="tx"> <tx:attributes> <tx:method name="save*" read-only="true" /> <tx:method name="update*" read-only="true" /> <tx:method name="delete*" read-only="true" /> <tx:method name="*" read-only="true" /> </tx:attributes> </tx:advice>
下面是修正以后的代码:session
<tx:advice transaction-manager="transactionManager" id="tx"> <tx:attributes> <tx:method name="save*" read-only="false" /> <tx:method name="update*" read-only="false" /> <tx:method name="delete*" read-only="false" /> <tx:method name="*" read-only="true" /> </tx:attributes> </tx:advice>
我来解(照)释(搬)一下原理:eclipse
经过getSession()取回来的session的flush mode 是FlushMode.NEVER,FlushMode.NEVER只支持read-only(),简而言之就是,只能对数据进行读的操做,其他的操做不被容许。只有当session的类型为FlushMode.AUTO时,才可以进行修改等操做。若是想把session的类型设为FlushMode.AUTO的话,就须要继承OpenSessionInViewFilter类,而后重写这个方法。不过我不是很推荐这个作法。若是你但愿这样作得话,请参阅博客:http://blog.sina.com.cn/s/blog_59bc146c0100emn2.html 。lua
若是须要再详细一点的了解的话,我摘录一下大牛的解释:spa
错误缘由:
OpenSessionInViewFilter在getSession的时候,会把获取回来的session的flush mode 设为FlushMode.NEVER。而后把该sessionFactory绑定到TransactionSynchronizationManager,使request的整个过程都使用同一个session,在请求事后再接除该sessionFactory的绑定,最后closeSessionIfNecessary根据该session是否已和transaction绑定来决定是否关闭session。在这个过程当中,若HibernateTemplate 发现自当前session有不是readOnly的transaction,就会获取到FlushMode.AUTO Session,使方法拥有写权限。也便是,若是有不是readOnly的transaction就能够由Flush.NEVER转为Flush.AUTO,拥有insert,update,delete操做权限,若是没有transaction,而且没有另外人为地设flush model的话,则doFilter的整个过程都是Flush.NEVER。因此受transaction(声明式的事务)保护的方法有写权限,没受保护的则没有。.net
博客原文地址:http://blog.csdn.net/tfy1332/article/details/8679711hibernate