先说解决方法:
- 只需要在 SSH 项目的 Service 层加上 org.springframework.transaction.annotation.Transactional 包下的注解:
@Transactional
- 问题就解决了
问题描述
ssh 项目操作数据库报错:
Struts Problem Report
Struts has detected an unhandled exception:
Messages:
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.
File: org/springframework/orm/hibernate5/HibernateTemplate.java
Line number: 1,093
Stacktraces
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.
org.springframework.orm.hibernate5.HibernateTemplate.checkWriteOperationAllowed(HibernateTemplate.java:1093)
org.springframework.orm.hibernate5.HibernateTemplate.lambda$save$11(HibernateTemplate.java:637)
org.springframework.orm.hibernate5.HibernateTemplate.doExecute(HibernateTemplate.java:383)
org.springframework.orm.hibernate5.HibernateTemplate.executeWithNativeSession(HibernateTemplate.java:349)
org.springframework.orm.hibernate5.HibernateTemplate.save(HibernateTemplate.java:636)
wiki.laona.dao.impl.CategoryDaoImpl.saveCategory(CategoryDaoImpl.java:22)
wiki.laona.service.impl.CategoryServiceImpl.save(CategoryServiceImpl.java:25)
wiki.laona.web.CategoryAction.add(CategoryAction.java:33)
sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
java.lang.reflect.Method.invoke(Method.java:498)
ognl.OgnlRuntime.invokeMethodInsideSandbox(OgnlRuntime.java:1266)
ognl.OgnlRuntime.invokeMethod(OgnlRuntime.java:1251)
ognl.OgnlRuntime.callAppropriateMethod(OgnlRuntime.java:1969)
ognl.ObjectMethodAccessor.callMethod(ObjectMethodAccessor.java:68)
com.opensymphony.xwork2.ognl.accessor.XWorkMethodAccessor.callMethodWithDebugInfo(XWorkMethodAccessor.java:98)
com.opensymphony.xwork2.ognl.accessor.XWorkMethodAccessor.callMethod(XWorkMethodAccessor.java:90)
ognl.OgnlRuntime.callMethod(OgnlRuntime.java:2045)
ognl.ASTMethod.getValueBody(ASTMethod.java:97)
ognl.SimpleNode.evaluateGetValueBody(SimpleNode.java:212)
ognl.SimpleNode.getValue(SimpleNode.java:258)
ognl.Ognl.getValue(Ognl.java:537)
ognl.Ognl.getValue(Ognl.java:501)
com.opensymphony.xwork2.ognl.OgnlUtil$3.execute(OgnlUtil.java:492)
com.opensymphony.xwork2.ognl.OgnlUtil.compileAndExecuteMethod(OgnlUtil.java:544)
com.opensymphony.xwork2.ognl.OgnlUtil.callMethod(OgnlUtil.java:490)
com.opensymphony.xwork2.DefaultActionInvocation.invokeAction(DefaultActionInvocation.java:438)
com.opensymphony.xwork2.DefaultActionInvocation.invokeActionOnly(DefaultActionInvocation.java:293)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:254)
org.apache.struts2.interceptor.debugging.DebuggingInterceptor.intercept(DebuggingInterceptor.java:250)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
com.opensymphony.xwork2.interceptor.DefaultWorkflowInterceptor.doIntercept(DefaultWorkflowInterceptor.java:179)
com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:99)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
com.opensymphony.xwork2.validator.ValidationInterceptor.doIntercept(ValidationInterceptor.java:263)
org.apache.struts2.interceptor.validation.AnnotationValidationInterceptor.doIntercept(AnnotationValidationInterceptor.java:49)
com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:99)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
com.opensymphony.xwork2.interceptor.ConversionErrorInterceptor.doIntercept(ConversionErrorInterceptor.java:142)
com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:99)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:140)
com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:99)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
com.opensymphony.xwork2.interceptor.ParametersInterceptor.doIntercept(ParametersInterceptor.java:140)
com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:99)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
com.opensymphony.xwork2.interceptor.StaticParametersInterceptor.intercept(StaticParametersInterceptor.java:201)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
org.apache.struts2.interceptor.MultiselectInterceptor.intercept(MultiselectInterceptor.java:67)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
org.apache.struts2.interceptor.DateTextFieldInterceptor.intercept(DateTextFieldInterceptor.java:133)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
org.apache.struts2.interceptor.CheckboxInterceptor.intercept(CheckboxInterceptor.java:89)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
org.apache.struts2.interceptor.FileUploadInterceptor.intercept(FileUploadInterceptor.java:243)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
com.opensymphony.xwork2.interceptor.ModelDrivenInterceptor.intercept(ModelDrivenInterceptor.java:101)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
com.opensymphony.xwork2.interceptor.ScopedModelDrivenInterceptor.intercept(ScopedModelDrivenInterceptor.java:142)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
com.opensymphony.xwork2.interceptor.ChainingInterceptor.intercept(ChainingInterceptor.java:160)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
com.opensymphony.xwork2.interceptor.PrepareInterceptor.doIntercept(PrepareInterceptor.java:175)
com.opensymphony.xwork2.interceptor.MethodFilterInterceptor.intercept(MethodFilterInterceptor.java:99)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
org.apache.struts2.interceptor.I18nInterceptor.intercept(I18nInterceptor.java:121)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
org.apache.struts2.interceptor.ServletConfigInterceptor.intercept(ServletConfigInterceptor.java:167)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
com.opensymphony.xwork2.interceptor.AliasInterceptor.intercept(AliasInterceptor.java:207)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
com.opensymphony.xwork2.interceptor.ExceptionMappingInterceptor.intercept(ExceptionMappingInterceptor.java:196)
com.opensymphony.xwork2.DefaultActionInvocation.invoke(DefaultActionInvocation.java:249)
org.apache.struts2.factory.StrutsActionProxy.execute(StrutsActionProxy.java:48)
org.apache.struts2.dispatcher.Dispatcher.serviceAction(Dispatcher.java:574)
org.apache.struts2.dispatcher.ExecuteOperations.executeAction(ExecuteOperations.java:79)
org.apache.struts2.dispatcher.filter.StrutsPrepareAndExecuteFilter.doFilter(StrutsPrepareAndExecuteFilter.java:141)
org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:193)
org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:166)
org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:202)
org.apache.catalina.core.StandardContextValve.__invoke(StandardContextValve.java:96)
org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:41002)
org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:526)
org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:139)
org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:92)
org.apache.catalina.valves.AbstractAccessLogValve.invoke(AbstractAccessLogValve.java:678)
org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:74)
org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:343)
org.apache.coyote.http11.Http11Processor.service(Http11Processor.java:408)
org.apache.coyote.AbstractProcessorLight.process(AbstractProcessorLight.java:66)
org.apache.coyote.AbstractProtocol$ConnectionHandler.process(AbstractProtocol.java:861)
org.apache.tomcat.util.net.NioEndpoint$SocketProcessor.doRun(NioEndpoint.java:1579)
org.apache.tomcat.util.net.SocketProcessorBase.run(SocketProcessorBase.java:49)
java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1149)
java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:624)
org.apache.tomcat.util.threads.TaskThread$WrappingRunnable.run(TaskThread.java:61)
java.lang.Thread.run(Thread.java:748)
You are seeing this page because development mode is enabled. Development mode, or devMode, enables extra debugging behaviors and reports to assist developers. To disable this mode, set:
struts.devMode=false
in your WEB-INF/classes/struts.properties file.
问题原因
因为我们在 hibernate 中使用 transactionManager 进行事务增强。但是由于默认事务是只读的,故出现 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. 报错。
如果帮到您,可以给个一键三连,谢谢!