java Spring @Transaction 不启动事务

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/7561360/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-30 20:31:10  来源:igfitidea点击:

Spring @Transaction not starting transactions

javahibernatespringtransactionstransactional

提问by Prashant Kalkar

I am using Spring 3 with Hibernate 3. I am trying to configure Spring declarative transaction, but no matter what I try, Spring transaction is not getting started.

我在 Hibernate 3 中使用 Spring 3。我正在尝试配置 Spring 声明性事务,但无论我尝试什么,Spring 事务都没有开始。

Here is my configuration

这是我的配置

File: applicationContext-hibernate.xml

文件:applicationContext-hibernate.xml

<tx:annotation-driven transaction-manager="txManager" />

<bean id="txManager" class="org.springframework.orm.hibernate3.HibernateTransactionManager">
<property name="sessionFactory" ref="sessionFactory" />
</bean>

<bean id="mdbDataSource" class="org.apache.commons.dbcp.BasicDataSource">
...
</bean>

<bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
 <property name="dataSource" ref="mdbDataSource" />
  <property name="annotatedClasses">
.....
</bean>

I have a class ServiceLocatorImpl which implements ServiceLocator interface

我有一个实现 ServiceLocator 接口的类 ServiceLocatorImpl

@Service("serviceLocator")
@Transactional
public class ServiceLocatorImpl implements  ApplicationContextAware, Serializable, ServletContextAware, ServiceLocator {
public ResultObject executeService( Map objArgs )
{
      if(TransactionSynchronizationManager.isActualTransactionActive()) {
          LOGGER.debug("ServiceLocator:executeService - Active transaction found");
      } else {
        LOGGER.error("No active transaction found");
      }
         ......
}
     ....
}

It seems to me that all my configuration is correct. But when executeService method is called, TransactionSynchronizationManager.isActualTransactionActive() is always returning false.

在我看来,我所有的配置都是正确的。但是当调用 executeService 方法时, TransactionSynchronizationManager.isActualTransactionActive() 总是返回 false。

Please help me solving this problem. Let me know if any more information required.

请帮我解决这个问题。如果需要更多信息,请告诉我。

Update:I have wired the ServiceLocator into one of the other classes, as follows:

更新:我已将 ServiceLocator 连接到其他类之一,如下所示:

@Autowired
private ServiceLocator serviceLocator; // ServiceLocator is interface

I am using Spring 3.0.0 version.

我使用的是 Spring 3.0.0 版本。

executeService() is one the method defined in the ServiceLocator interface. I updated the code to throw exception instead of just logging an error. Following is the stack trace, I don't see any proxy creation in this trace. Please help.

executeService() 是 ServiceLocator 接口中定义的方法之一。我更新了代码以抛出异常而不是仅仅记录错误。以下是堆栈跟踪,我在此跟踪中没有看到任何代理创建。请帮忙。

    java.lang.RuntimeException: No active transaction found
at com.nihilent.venice.common.service.ServiceLocatorImpl.logTransactionStatus(ServiceLocatorImpl.java:102)
at com.nihilent.venice.common.service.ServiceLocatorImpl.executeService(ServiceLocatorImpl.java:47)
at com.nihilent.venice.web.controller.CommonController.handleRequest(CommonController.java:184)
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.springframework.web.bind.annotation.support.HandlerMethodInvoker.doInvokeMethod(HandlerMethodInvoker.java:710)
at org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:167)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:414)
at org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:402)
at org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:771)
at org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:716)
at org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:647)
at org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:552)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:617)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.tuckey.web.filters.urlrewrite.RuleChain.handleRewrite(RuleChain.java:176)
at org.tuckey.web.filters.urlrewrite.RuleChain.doRules(RuleChain.java:145)
at org.tuckey.web.filters.urlrewrite.UrlRewriter.processRequest(UrlRewriter.java:92)
at org.tuckey.web.filters.urlrewrite.UrlRewriteFilter.doFilter(UrlRewriteFilter.java:381)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.ApplicationDispatcher.invoke(ApplicationDispatcher.java:646)
at org.apache.catalina.core.ApplicationDispatcher.processRequest(ApplicationDispatcher.java:436)
at org.apache.catalina.core.ApplicationDispatcher.doForward(ApplicationDispatcher.java:374)
at org.apache.catalina.core.ApplicationDispatcher.forward(ApplicationDispatcher.java:302)
at org.apache.jasper.runtime.PageContextImpl.doForward(PageContextImpl.java:709)
at org.apache.jasper.runtime.PageContextImpl.forward(PageContextImpl.java:680)
at org.apache.jsp.index_jsp._jspService(index_jsp.java:57)
at org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:386)
at org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:313)
at org.apache.jasper.servlet.JspServlet.service(JspServlet.java:260)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:717)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.tuckey.web.filters.urlrewrite.RuleChain.handleRewrite(RuleChain.java:176)
at org.tuckey.web.filters.urlrewrite.RuleChain.doRules(RuleChain.java:145)
at org.tuckey.web.filters.urlrewrite.UrlRewriter.processRequest(UrlRewriter.java:92)
at org.tuckey.web.filters.urlrewrite.UrlRewriteFilter.doFilter(UrlRewriteFilter.java:381)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at com.nihilent.venice.web.filter.DyanamicResponseHeaderFilter.doFilter(DyanamicResponseHeaderFilter.java:33)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at com.opensymphony.module.sitemesh.filter.PageFilter.parsePage(PageFilter.java:118)
at com.opensymphony.module.sitemesh.filter.PageFilter.doFilter(PageFilter.java:52)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:343)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:109)
at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:83)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:97)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:100)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:78)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:54)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:35)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:188)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:188)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:79)
at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:355)
at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:149)
at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237)
at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at com.nihilent.venice.web.filter.RequestFilter.doFilter(RequestFilter.java:44)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.springframework.web.filter.CharacterEncodingFilter.doFilterInternal(CharacterEncodingFilter.java:88)
at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298)
at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:859)
at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588)
at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489)
at java.lang.Thread.run(Thread.java:619)

Update [Solved]I got the issue fixed. Before giving the answer as how it was fixed, I need to provide some more information. I am using Spring MVC in my project. The control DispatchServlet is configured in the web.xml. This front controller has a configuration xml file abc-servlet.xml (abc being the servlet name in web.xml). I have other spring configuration files too which are defined as context-paramin web.xml. One of the file is applicationContext-hibernate.xmlfile.

更新 [已解决]问题已解决。在给出它是如何修复的答案之前,我需要提供更多信息。我在我的项目中使用 Spring MVC。在 web.xml 中配置了控件 DispatchServlet。这个前端控制器有一个配置 xml 文件 abc-servlet.xml(abc 是 web.xml 中的 servlet 名称)。我也有其他 spring 配置文件,它们context-paramweb.xml. 文件之一是applicationContext-hibernate.xml文件。

I defined the txManagerand <tx:annotation-driven />, in the applicationContext-hibernate.xmlfile. Today I was wondering whether @Autowired and @Transactional work with together, so I Google the information, and found this thread

我在文件中定义了txManagerand 。今天我想知道@Autowired 和@Transactional 是否一起工作,所以我谷歌了信息,并找到了这个线程<tx:annotation-driven />applicationContext-hibernate.xml

http://forum.springsource.org/showthread.php?48815-Repository-Autowired-Transaction-not-returning-proxy-and-causes-exception

http://forum.springsource.org/showthread.php?48815-Repository-Autowired-Transaction-not-returning-proxy-and-causes-exception

The thread talk about similar problem, and this solves the problem.

该线程讨论了类似的问题,这解决了问题。

I implemented one of the suggestion and added <tx:annotation-driven .../> to my servlet's application context xml and it fixes the problem.

I implemented one of the suggestion and added <tx:annotation-driven .../> to my servlet's application context xml and it fixes the problem.

Thinking that I also moved my <tx:annotation-driven />into abc-servlet.xml file and it worked.

认为我也将我的<tx:annotation-driven />文件移入 abc-servlet.xml 文件并且它起作用了。

My logs are now shoulding the required messages:

我的日志现在应该包含所需的消息:

[venice] DEBUG [http-8080-1] 27 Sep 2011 14:24:06,312 ServiceLocatorImpl.logTransactionStatus(100) | ServiceLocator:executeService - Active transaction found

[venice] DEBUG [http-8080-1] 27 Sep 2011 14:24:06,312 ServiceLocatorImpl.logTransactionStatus(100) | ServiceLocator:executeService - Active transaction found

Thanks to everyone for Helping. May be this information will be helpful to someone. I would still like to hear about the explanation as why it was not working earlier.

感谢大家的帮助。可能这些信息会对某人有所帮助。我仍然想听听关于为什么它没有更早工作的解释。

回答by Ryan Stewart

My guess would be that you're trying to do something like:

我的猜测是您正在尝试执行以下操作:

ServiceLocator locator = new ServiceLocatorImpl();
...
locator.executeService(someMap);

and then being surprised that there's no transaction. Transaction management and all other Spring services only apply to beans in the application context*. You need to get your instance from the context one way or another instead of just instantiating one. Or else your locator bean is in a separate application context than the one where you declare tx:annotation-driven.

然后惊讶地发现没有交易。事务管理和所有其他 Spring 服务仅适用于应用程序上下文中的 bean*。您需要以一种或另一种方式从上下文中获取您的实例,而不仅仅是实例化一个。否则,您的定位器 bean 位于与您声明的应用程序上下文不同的应用程序上下文中tx:annotation-driven

*Unless you're using AspectJ build- or load-time bytecode weavingwith Spring.

*除非您在Spring 中使用AspectJ 构建或加载时字节码编织

Edit:The problem was exactly what I said (the second part). You create two application contexts. You were creating your ServiceLocator in the first one, but you only enabled annotation-driven transactions in the second one. You appear to not understand the boundaries between the contexts. Generally--at least in my experience--the "business" beans, like your ServiceLocator, live in the root context, which is the one started by the ContextLoaderListenerand configured via contextConfigLocation. Controllers and other beans that configure or are used by a DispatcherServlet live in another context associated with that servlet which is configured by the *-servlet.xmlfile. This context becomes a child context of the root context, and the beans in it can be injected with beans from the root context, though not vice versa.

编辑:问题正是我所说的(第二部分)。您创建了两个应用程序上下文。您在第一个中创建了 ServiceLocator,但在第二个中仅启用了注释驱动的事务。您似乎不了解上下文之间的界限。一般-至少在我的经验- “生意”豆,喜欢你的服务定位,住在根上下文,这是一个由开始ContextLoaderListener,并通过配置contextConfigLocation。配置或由 DispatcherServlet 使用的控制器和其他 bean 位于与该 servlet 相关联的另一个上下文中,该上下文由*-servlet.xml文件配置。这个上下文成为根上下文的子上下文,其中的bean可以从根上下文注入bean,反之则不行。

From my perspective, you've broken things worse than they were before by adding tx:annotation-drivento the child context associated to your DispatcherServlet. Instead, you should ensure that the ServiceLocator is created in the root context, where transactional services are already available and are where they belong.

从我的角度来看,通过添加tx:annotation-driven到与 DispatcherServlet 关联的子上下文,您已经破坏了比以前更糟糕的事情。相反,您应该确保在根上下文中创建 ServiceLocator,其中事务服务已经可用并且属于它们。

回答by Sergio

You should simply rename your "txManager" to "transactionManager". From the EnableTransactionManagement's JavaDoc:

您应该简单地将“txManager”重命名为“transactionManager”。从EnableTransactionManagementJavaDoc

…in the XML case, the name is "transactionManager". The <tx:annotation-driven/>is hard-wired to look for a bean named "transactionManager" by default…

...在 XML 的情况下,名称是“transactionManager”。<tx:annotation-driven/>默认情况下,它是硬连接来查找名为“transactionManager”的 bean...