Tha*_*ish 10 spring hibernate cxf transactionmanager spring-data-jpa
编辑:对于可能对此问题感兴趣的任何人,我在问题的最后提供了相关解决方案的问题分析.
我正在为Web应用程序配置模块,其中我使用的是Spring 3.2,Hibernate 4.1,Spring Data JPA 1.3和Apache CXF 2.5(特别是JAX-RS模块).我有以下配置(工作完全正常,为简明起见,省略了详细信息):
@Bean(name = "entityManagerFactory")
public LocalContainerEntityManagerFactoryBean getEntityManagerFactory() throws SQLException{
LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
//...
return factory;
}
@Bean(name = "transactionManager")
public JpaTransactionManager getTransactionManager() throws SQLException{
JpaTransactionManager manager = new JpaTransactionManager();
//...
return manager;
}
@Bean(name = "persistenceExceptionTranslator")
public PersistenceExceptionTranslator getPersistenceExceptionTranslator(){
return new HibernateExceptionTranslator();
}
Run Code Online (Sandbox Code Playgroud)
我的问题是我必须依赖一些定义自己的外部模块PlatformTransactionManager,所以我发现自己同时使用更多的事务管理器.Transactional.html #value()可以很容易地解决这个问题,所以无论我需要在哪里使用@Transactional,我都要使用我必须用于该事务的事务管理器的名称来限定注释.
我想将我在模块中定义的事务管理器的名称更改为更有意义的名称,以满足外部模块的标准.因此,例如,externalModule1将其经理定义为externalModule1TransactionManager我想要的
@Bean(name = "myModuleransactionManager")
public JpaTransactionManager getTransactionManager() throws SQLException{
JpaTransactionManager manager = new JpaTransactionManager();
//...
return manager;
}
Run Code Online (Sandbox Code Playgroud)
这似乎很容易,不幸的是,当我做这个改变时(我改变了相应的用法,@Transactional#value()我得到了一个例外.
java.lang.RuntimeException: org.apache.cxf.interceptor.Fault: No bean named 'transactionManager' is defined
at org.apache.cxf.interceptor.AbstractFaultChainInitiatorObserver.onMessage(AbstractFaultChainInitiatorObserver.java:110)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:323)
at org.apache.cxf.transport.ChainInitiationObserver.onMessage(ChainInitiationObserver.java:123)
at org.apache.cxf.transport.http.AbstractHTTPDestination.invoke(AbstractHTTPDestination.java:207)
at org.apache.cxf.transport.servlet.ServletController.invokeDestination(ServletController.java:213)
at org.apache.cxf.transport.servlet.ServletController.invoke(ServletController.java:154)
at org.apache.cxf.transport.servlet.CXFNonSpringServlet.invoke(CXFNonSpringServlet.java:126)
at org.apache.cxf.transport.servlet.AbstractHTTPServlet.handleRequest(AbstractHTTPServlet.java:185)
at org.apache.cxf.transport.servlet.AbstractHTTPServlet.doGet(AbstractHTTPServlet.java:113)
at javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
at org.apache.cxf.transport.servlet.AbstractHTTPServlet.service(AbstractHTTPServlet.java:164)
at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:222)
at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:123)
at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:171)
at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:99)
at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:936)
at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:1004)
at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:589)
at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:312)
at java.util.concurrent.ThreadPoolExecutor$Worker.runTask(ThreadPoolExecutor.java:895)
at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:918)
at java.lang.Thread.run(Thread.java:662)
Caused by: org.apache.cxf.interceptor.Fault: No bean named 'transactionManager' is defined
at org.apache.cxf.service.invoker.AbstractInvoker.createFault(AbstractInvoker.java:155)
at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:121)
at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:167)
at org.apache.cxf.jaxrs.JAXRSInvoker.invoke(JAXRSInvoker.java:94)
at org.apache.cxf.interceptor.ServiceInvokerInterceptor$1.run(ServiceInvokerInterceptor.java:58)
at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:439)
at java.util.concurrent.FutureTask$Sync.innerRun(FutureTask.java:303)
at java.util.concurrent.FutureTask.run(FutureTask.java:138)
at org.apache.cxf.workqueue.SynchronousExecutor.execute(SynchronousExecutor.java:37)
at org.apache.cxf.interceptor.ServiceInvokerInterceptor.handleMessage(ServiceInvokerInterceptor.java:106)
at org.apache.cxf.phase.PhaseInterceptorChain.doIntercept(PhaseInterceptorChain.java:263)
... 25 more
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named 'transactionManager' is defined
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBeanDefinition(DefaultListableBeanFactory.java:568)
at org.springframework.beans.factory.support.AbstractBeanFactory.getMergedLocalBeanDefinition(AbstractBeanFactory.java:1099)
at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:278)
at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:198)
at org.springframework.transaction.interceptor.TransactionAspectSupport.determineTransactionManager(TransactionAspectSupport.java:246)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:100)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.data.jpa.repository.support.LockModeRepositoryPostProcessor$LockModePopulatingMethodIntercceptor.invoke(LockModeRepositoryPostProcessor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:91)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:155)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
at sun.proxy.$Proxy98.save(Unknown Source)
at myModule.package.SomeOtherClass.someOtherMethod(SomeOtherClass.java:114)
at myModule.package.SomeOtherClass$$FastClassByCGLIB$$2bda5a73.invoke(<generated>)
at org.springframework.cglib.proxy.MethodProxy.invoke(MethodProxy.java:204)
at org.springframework.aop.framework.CglibAopProxy$CglibMethodInvocation.invokeJoinpoint(CglibAopProxy.java:698)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:150)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:110)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172)
at org.springframework.aop.framework.CglibAopProxy$DynamicAdvisedInterceptor.intercept(CglibAopProxy.java:631)
at myModule.package.SomeClass$$EnhancerByCGLIB$$37044080.myMethod(<generated>)
at myModule.package.SomeClass.someMethod(SomeClass.java:64)
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.apache.cxf.service.invoker.AbstractInvoker.performInvocation(AbstractInvoker.java:173)
at org.apache.cxf.service.invoker.AbstractInvoker.invoke(AbstractInvoker.java:89)
... 34 more
Run Code Online (Sandbox Code Playgroud)
特别是,我想集中注意力
myModule.package.SomeOtherClass.someOtherMethod(SomeClass.java:114)
Run Code Online (Sandbox Code Playgroud)
和
myModule.package.SomeClass.someMethod(SomeClass.java:64)
Run Code Online (Sandbox Code Playgroud)
他们的代码看起来像
@Transactional("myModuleransactionManager")
public ... someOtherMethod(){
...
}
Run Code Online (Sandbox Code Playgroud)
和
public ... someMethod(){
...
}
Run Code Online (Sandbox Code Playgroud)
所以,根据我的理解,这个配置应该有效,为什么会抛出这个异常呢?是否需要标准的命名事务管理器?或者它是由cxf引起的?我发现同样的应用程序(内涉及多个事务管理的一些问题例如1,例2),但在这些问题接受的答案开车到我的解决方案.我误解了什么,我做错了什么?
感谢所有愿意阅读这个长期问题的人,直到这里!
编辑提供基于Michail答案的完整解释:使用Spring Data JPA,需要定义存储库接口以连接到数据库.someOtherMethod确实在调用我的一个存储库,定义为:
@Repository("myRepository")
@Transactional(propagation = Propagation.NESTED, value = "myModuleransactionManager")
public interface MyRepository extends JpaRepository<MyEntity, Integer>
{
}
Run Code Online (Sandbox Code Playgroud)
这看起来很好,但是查看JpaRepository实现源代码(所以,看着org.springframework.data.jpa.repository.support.SimpleJpaRepository我发现save(以及其他更新方法)注释了@Transactional.代码来自SimpleJpaRepository
@Transactional
public <S extends T> S save(S entity) {
if (entityInformation.isNew(entity)) {
em.persist(entity);
return entity;
} else {
return em.merge(entity);
}
}
Run Code Online (Sandbox Code Playgroud)
因此,在使用Spring Data JPA时,必须使用缺省事务管理器(名为transactionManager).对我的目标不好,但至少我现在知道就是这样!
看起来你的someOtherMethod调用任何其他@Transactional组件(一些类与save方法).我认为它有@Transactinal()(空)注释(使用默认bean命名transactionManager).
您可能会TransactionInterceptor在stacktrace中看到2个位置.请提供一些有关它的细节.
我怀疑您只需要确保您的存储库在@EnableJpaRepositories批注中使用正确命名的事务管理器即可。
即
@Configuration
@EnableTransactionManagement
@EnableJpaRepositories(
entityManagerFactoryRef = "fooEntityManagerFactory",
transactionManagerRef = "fooTransactionManager",
basePackages = {"com.sctrcd.multidsdemo.integration.repositories.foo"})
public class FooConfig {
//...
}
Run Code Online (Sandbox Code Playgroud)
我花了一些时间来弄清细节,因此我在这里提供了关于如何配置Spring Data JPA存储库以与多个数据源一起使用的完整说明:
xml配置中有多个jpa:repositories,如何使用Spring Java配置与@EnableJPARepositories配置?
还有一个完整的项目在这里演示:
https://github.com/gratiartis/multids-demo
| 归档时间: |
|
| 查看次数: |
15816 次 |
| 最近记录: |