本文介绍了如何在Spring 4.0.6中全局设置FlushMode for Hibernate 4.3.5.Final?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧! 问题描述 29岁程序员,3月因学历无情被辞! 我试图用Hibernate 4.3.5.Final和Spring 4.0.6升级我们的应用程序。任何在我的数据库写入操作的应用程序中出现如下错误: 原因:org.springframework.dao.InvalidDataAccessApiUsageException:在只读模式下不允许写操作(FlushMode.MANUAL):将会话变为FlushMode.COMMIT / AUTO或从事务定义中删除'readOnly'标记。 at org.springframework.orm.hibernate4.HibernateTemplate.checkWriteOperationAllowed(HibernateTemplate.java:1135) at org.springframework.orm.hibernate4.HibernateTemplate $ 26.doInHibernate(HibernateTemplate.java:826)在org.springframework.orm.hibernate4.HibernateTemplate.doExecute(HibernateTemplate.java:340)在org.springframework.orm.hibernate4.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:308) at org。 springframework.orm.hibernate4.HibernateTemplate.deleteAll(HibernateTemplate.java:823) ... 以下是sessionFactory和transactionManager的spring配置: < bean id =sessionFactoryclass =org。 springframework.orm.hibernate4.LocalSessionFactoryBean> < property name =dataSourceref =dataSource/> < property name =mappingResources> < list> <值> com / mycompany / Person.hbm.xml< /值> < / list> < / property> < property name =hibernateProperties> <道具> < prop key =hibernate.dialect> org.hibernate.dialect.HSQLDialect< / prop> < /道具> < / property> < / bean> < bean id =transactionManagerclass =org.springframework.orm.hibernate4.HibernateTransactionManager> < property name =sessionFactoryref =sessionFactory/> < / bean> 为了全局设置flushMode,以便应用程序的工作方式与以前相同,我需要将flushMode设置为全局AUTO,所以我不想使用@Transactional(readOnly = false)做法。 $ b $ 2 在下面的帖子中,有人建议将singleSession设置为false, Java / Hibernate - 写入操作在read-只有模式 Spring文档建议指定singleSession=false有副作用: http://docs.spring。 io / spring / docs / 4.0.6.RELEASE / javadoc-api / org / springframework / orm / hibernate3 / support / OpenSessionInViewInterceptor.html 我已经在web.xml中看到了很多像下面这样的建议,它允许您拦截hibernate3会话并使用eg提供会话版本flushMode.AUTO。但是,在使用org.springframework.orm.hibernate4.support.OpenSessionInViewFilter时,这在hibernate 4中不起作用。 < ;滤光器> < filter-name> openSessionInViewFilter< / filter-name> < filter-class> org.springframework.orm.hibernate3.support.OpenSessionInViewFilter< / filter-class> < init-param> < param-name> flushMode< / param-name> <参数值> AUTO< /参数值> < / init-param> < / filter> 4: 正在使用JPA事务管理器,它遵循复杂的HibernateJpaDialect重新实现。我目前不使用JPA,这种方法似乎不够简单。 如何设置刷新模式为COMMIT在我的配置文件中? 5: 我试过在我的春天配置(以下关于 Spring ORM 4.0.5和Hibernate 4.3.5 - 无法保存到数据库),它似乎不工作,并且人们建议使用web.xml方法: Spring和Hibernate突然将事务设置为只读 < tx:advice id =transactionAdvicetransaction-manager =transactionManager> < tx:attributes> < tx:method name =*read-only =false/> < / tx:属性> < / tx:advice> 问题: 任何人都可以提出一个简单的方法来允许为Hibernate 4.3.5.Final和Spring 4.0.6设置FlushMode吗?解决方案我最终用自定义实现覆盖了OpenSessionInViewFilter: 1: web.xml: < filter> < filter-name> openSessionInViewFilter< / filter-name> < filter-class> com.mycompany.AutoFlushOpenSessionInViewFilter< / filter-class> < / filter> < filter-mapping> < filter-name> openSessionInViewFilter< / filter-name> < url-pattern> / *< / url-pattern> < / filter-mapping> < listener> < listener-class> org.springframework.web.context.ContextLoaderListener< / listener-class> < / listener> Spring需要ContextLoaderListener才能工作。 $ b AutoFlushOpenSessionInViewFilter应用于拦截来自/ * url模式的请求 $ b 2: AutoFlushOpenSessionInViewFilter: import org.hibernate.FlushMode; import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.springframework.dao.DataAccessResourceFailureException; import org.springframework.orm.hibernate4.support.OpenSessionInViewFilter; public class AutoFlushOpenSessionInViewFilter extends OpenSessionInViewFilter { protected session openSession(SessionFactory sessionFactory)throws DataAccessResourceFailureException { try { Session session = sessionFactory.openSession() ; session.setFlushMode(FlushMode.AUTO); //这行改变默认行为 return session; catch(HibernateException ex){ throw new DataAccessResourceFailureException(Could not open Hibernate Session,ex); } } } OpenSessionInViewFilter是拦截hibernate会话的默认方式( http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/orm/hibernate4/support/OpenSessionInViewFilter.html ) openSession方法打开一个hibernate会话。 Hibernate会使用这个会话而不是创建一个新的会话。 hibernate3.support.OpenSessionInViewFilter允许你提供一个FlushMode,hibernate4.support.OpenSessionInViewFilter硬编码值,所以我用它覆盖它自己的实现 确保sessionFactory bean名称是sessionFactory。否则,您需要将sessionFactoryBeanName设置为web.xml中的过滤器init-param 3: 所有Spring bean都需要在Web应用程序上下文(web.xml)中注册: <的context-param> < param-name> contextConfigLocation< / param-name> < param-value> classpath:appContext.xml ... < / param-value> < / context-param> 4: 确保您获得当您需要使用它们时,只能从应用程序上下文中获取Spring Bean。以下是一个示例: http://sujitpal.blogspot.co.uk/2007/03/accessing-spring-beans-from-legacy-code.html 确保只有一个正在创建的Spring bean的副本! 如果使用org.springframework.context.support.ClassPathXmlApplicationContext加载Spring bean,那么这些bean将不会被过滤器拾取。 5: 在我的情况中,还需要一个contextId <上下文-param> < param-name> contextId< / param-name> < param-value> myApp< / param-value> < description>提供过滤器时所需的contextId< / description> < / context-param> 否则我会遇到以下问题: java的监听器实例。 lang.NoSuchMethodError:javax.servlet.ServletContext.getContextPath()Ljava / lang / String; at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:384) at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306)在org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106) at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3827) at org.apache .catalina.core.StandardContext.start(StandardContext.java:4343) at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:823) at org.apache.catalina.core .ContainerBase.addChild(ContainerBase.java:807) at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:595) at org.apache.catalina.core.StandardHostDeployer.addChild (StandardHostDeployer.java:903) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessor Impl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.apache.commons.beanutils.MethodUtils.invokeMethod(MethodUtils。 at org.apache.commons.digester.SetNextRule.end(SetNextRule.java:256) at org.apache.commons.digester.Rule.end(Rule.java:276) at org.apache.commons.digester.Digester.endElement(Digester.java:1058) at org.apache.catalina.util.CatalinaDigester.endElement(CatalinaDigester.java:76) at org.apache.xerces.parsers.AbstractSAXParser.endElement(Unknown Source) ... 如果有人对此感兴趣,以下是我的Ivy.xml中的内容 <! - Spring 4.0.6.RELEASE - > < dependency org =org.springframeworkname =spring-aoprev =4.0.6.RELEASEconf =compile-> master,sources,javadoc/> < dependency org =org.springframeworkname =spring-beansrev =4.0.6.RELEASEconf =compile-> master,sources,javadoc/> < dependency org =org.springframeworkname =spring-corerev =4.0.6.RELEASEconf =compile-> master,sources,javadoc/> < dependency org =org.springframeworkname =spring-expressionrev =4.0.6.RELEASEconf =compile-> master,sources,javadoc/> < dependency org =org.springframeworkname =spring-contextrev =4.0.6.RELEASEconf =compile-> master,sources,javadoc/> < dependency org =org.springframeworkname =spring-jdbcrev =4.0.6.RELEASEconf =compile-> master,sources,javadoc/> < dependency org =org.springframeworkname =spring-ormrev =4.0.6.RELEASEconf =compile-> master,sources,javadoc/> < dependency org =org.springframeworkname =spring-txrev =4.0.6.RELEASEconf =compile-> master,sources,javadoc/> < dependency org =org.springframeworkname =spring-webrev =4.0.6.RELEASEconf =compile-> master,sources,javadoc/> < dependency org =aopalliancename =aopalliancerev =1.0conf =compile-> master,sources,javadoc/> < dependency org =org.hibernatename =hibernate-corerev =4.3.5.Finalconf =compile-> master,compile,sources/> < dependency org =net.sf.ehcachename =ehcache-corerev =2.4.8conf =compile-> master,sources,javadoc/> < dependency org =org.slf4jname =slf4j-apirev =1.7.5conf =compile-> master,sources,javadoc/> 希望这可以帮助遇到同一问题的任何人当升级Spring和Hibernate时。 I'm trying to upgrade our application with Hibernate 4.3.5.Final and Spring 4.0.6. Any where in my app with database write operation gets an error as below:Caused by: 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.hibernate4.HibernateTemplate.checkWriteOperationAllowed(HibernateTemplate.java:1135) at org.springframework.orm.hibernate4.HibernateTemplate$26.doInHibernate(HibernateTemplate.java:826) at org.springframework.orm.hibernate4.HibernateTemplate.doExecute(HibernateTemplate.java:340) at org.springframework.orm.hibernate4.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:308) at org.springframework.orm.hibernate4.HibernateTemplate.deleteAll(HibernateTemplate.java:823) ...The follwing is my spring configuration for sessionFactory and transactionManager:<bean id="sessionFactory" class="org.springframework.orm.hibernate4.LocalSessionFactoryBean"> <property name="dataSource" ref="dataSource"/> <property name="mappingResources"> <list> <value>com/mycompany/Person.hbm.xml</value> </list> </property> <property name="hibernateProperties"> <props> <prop key="hibernate.dialect">org.hibernate.dialect.HSQLDialect</prop> </props> </property></bean><bean id="transactionManager" class="org.springframework.orm.hibernate4.HibernateTransactionManager"> <property name="sessionFactory" ref="sessionFactory"/></bean>1:In order to globally set the flushMode so that the app works the same way as before, I need to set flushMode to AUTO globally, so I don't want to use the @Transactional(readOnly = false) approach.2:In the post below, someone suggests setting singleSession to false,Java / Hibernate - Write operations are not allowed in read-only modeThe Spring documentations suggests that specifying "singleSession"="false" has side effect:http://docs.spring.io/spring/docs/4.0.6.RELEASE/javadoc-api/org/springframework/orm/hibernate3/support/OpenSessionInViewInterceptor.html3:I have seen quite a few suggestions like the below in web.xml, which allows you to intercept the hibernate3 session and provide a version of the session with e.g. flushMode.AUTO. However, this doesn't work in hibernate 4 when you use org.springframework.orm.hibernate4.support.OpenSessionInViewFilter.<filter> <filter-name>openSessionInViewFilter</filter-name> <filter-class>org.springframework.orm.hibernate3.support.OpenSessionInViewFilter</filter-class> <init-param> <param-name>flushMode</param-name> <param-value>AUTO</param-value> </init-param></filter>4:The approach suggested below is using JPA transaction manager, which follows a complicate re-implementation of HibernateJpaDialect. I'm not using JPA at the moment and this approach doesn't seem to be simple enough.How do I set flush mode to "COMMIT" in my configuration files?5:I have tried having the following in my spring configuration (following a suggestion on Spring ORM 4.0.5 and Hibernate 4.3.5 - Cant save to database),it doesn't seem to work and people suggest using the web.xml approach:Spring and Hibernate suddenly set the transaction to readonly<tx:advice id="transactionAdvice" transaction-manager="transactionManager" > <tx:attributes> <tx:method name="*" read-only="false"/> </tx:attributes></tx:advice>Question:Can anyone suggest a simple approach to allow setting FlushMode for Hibernate 4.3.5.Final and Spring 4.0.6? 解决方案 I ended up overriding OpenSessionInViewFilter with custom implementation:1:web.xml:<filter> <filter-name>openSessionInViewFilter</filter-name> <filter-class>com.mycompany.AutoFlushOpenSessionInViewFilter</filter-class></filter><filter-mapping> <filter-name>openSessionInViewFilter</filter-name> <url-pattern>/*</url-pattern></filter-mapping><listener> <listener-class>org.springframework.web.context.ContextLoaderListener</listener-class></listener>ContextLoaderListener is required for Spring to work.AutoFlushOpenSessionInViewFilter is applied to intercept requests from the /* url pattern2:AutoFlushOpenSessionInViewFilter:import org.hibernate.FlushMode;import org.hibernate.HibernateException;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.springframework.dao.DataAccessResourceFailureException;import org.springframework.orm.hibernate4.support.OpenSessionInViewFilter;public class AutoFlushOpenSessionInViewFilter extends OpenSessionInViewFilter { protected Session openSession(SessionFactory sessionFactory) throws DataAccessResourceFailureException { try { Session session = sessionFactory.openSession(); session.setFlushMode(FlushMode.AUTO); // This line changes the default behavior return session; } catch (HibernateException ex) { throw new DataAccessResourceFailureException("Could not open Hibernate Session", ex); } }}OpenSessionInViewFilter is the default way to intercept hibernate sessions (http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/orm/hibernate4/support/OpenSessionInViewFilter.html)The openSession method opens a hibernate session. Hibernate would use this session instead of creating a new onehibernate3.support.OpenSessionInViewFilter allows you to provide a FlushMode, hibernate4.support.OpenSessionInViewFilter hard codes the value, so I override it with my own implementationMake sure your sessionFactory bean name is sessionFactory. Otherwise you need to set the sessionFactoryBeanName as a filter init-param in web.xml3:All the Spring beans need to be registered within the Web application context (web.xml):<context-param> <param-name>contextConfigLocation</param-name> <param-value> classpath:appContext.xml ... </param-value></context-param>4:Make sure you get your spring beans only from the application context when you need to use them. The following is a how to example:http://sujitpal.blogspot.co.uk/2007/03/accessing-spring-beans-from-legacy-code.htmlMake sure there is only one copy of the Spring beans being created!If you use org.springframework.context.support.ClassPathXmlApplicationContext to load Spring beans, these beans would not be picked up by the filter.5:In my case, a contextId is also required<context-param> <param-name>contextId</param-name> <param-value>myApp</param-value> <description>Required contextId when filter is supplied</description></context-param>Otherwise I get the issue below:2014-09-02 10:59:50 StandardContext[/myApp]Exception sending context initialized event to listener instance of class org.springframework.web.context.ContextLoaderListenerjava.lang.NoSuchMethodError: javax.servlet.ServletContext.getContextPath()Ljava/lang/String; at org.springframework.web.context.ContextLoader.configureAndRefreshWebApplicationContext(ContextLoader.java:384) at org.springframework.web.context.ContextLoader.initWebApplicationContext(ContextLoader.java:306) at org.springframework.web.context.ContextLoaderListener.contextInitialized(ContextLoaderListener.java:106) at org.apache.catalina.core.StandardContext.listenerStart(StandardContext.java:3827) at org.apache.catalina.core.StandardContext.start(StandardContext.java:4343) at org.apache.catalina.core.ContainerBase.addChildInternal(ContainerBase.java:823) at org.apache.catalina.core.ContainerBase.addChild(ContainerBase.java:807) at org.apache.catalina.core.StandardHost.addChild(StandardHost.java:595) at org.apache.catalina.core.StandardHostDeployer.addChild(StandardHostDeployer.java:903) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:606) at org.apache.commons.beanutils.MethodUtils.invokeMethod(MethodUtils.java:216) at org.apache.commons.digester.SetNextRule.end(SetNextRule.java:256) at org.apache.commons.digester.Rule.end(Rule.java:276) at org.apache.commons.digester.Digester.endElement(Digester.java:1058) at org.apache.catalina.util.CatalinaDigester.endElement(CatalinaDigester.java:76) at org.apache.xerces.parsers.AbstractSAXParser.endElement(Unknown Source) ...If anyone is interested, the following is what's in my Ivy.xml<!--Spring 4.0.6.RELEASE --><dependency org="org.springframework" name="spring-aop" rev="4.0.6.RELEASE" conf="compile->master,sources,javadoc"/><dependency org="org.springframework" name="spring-beans" rev="4.0.6.RELEASE" conf="compile->master,sources,javadoc"/><dependency org="org.springframework" name="spring-core" rev="4.0.6.RELEASE" conf="compile->master,sources,javadoc"/><dependency org="org.springframework" name="spring-expression" rev="4.0.6.RELEASE" conf="compile->master,sources,javadoc"/><dependency org="org.springframework" name="spring-context" rev="4.0.6.RELEASE" conf="compile->master,sources,javadoc"/><dependency org="org.springframework" name="spring-jdbc" rev="4.0.6.RELEASE" conf="compile->master,sources,javadoc"/><dependency org="org.springframework" name="spring-orm" rev="4.0.6.RELEASE" conf="compile->master,sources,javadoc"/><dependency org="org.springframework" name="spring-tx" rev="4.0.6.RELEASE" conf="compile->master,sources,javadoc"/><dependency org="org.springframework" name="spring-web" rev="4.0.6.RELEASE" conf="compile->master,sources,javadoc"/><dependency org="aopalliance" name="aopalliance" rev="1.0" conf="compile->master,sources,javadoc"/><!--Hibernate 4.3.5--><dependency org="org.hibernate" name="hibernate-core" rev="4.3.5.Final" conf="compile->master,compile,sources"/><dependency org="net.sf.ehcache" name="ehcache-core" rev="2.4.8" conf="compile->master,sources,javadoc"/><dependency org="org.slf4j" name="slf4j-api" rev="1.7.5" conf="compile->master,sources,javadoc"/>Hope this helps anyone who comes across the same issue when upgrading Spring and Hibernate. 这篇关于如何在Spring 4.0.6中全局设置FlushMode for Hibernate 4.3.5.Final?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持! 上岸,阿里云!
07-26 05:54