这几天配置spring data jpa时,使用声明式事务碰到了一个奇怪的问题,无论怎么配置xml或在方法上使用@Transactional(value = "tm1")都会报如下找不到事务管理器的错误:
Exception in thread "main" org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [org.springframework.transaction.PlatformTransactionManager] is defined: expected single matching bean but found 2: tm2,tm1
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:365)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:331)
at org.springframework.transaction.interceptor.TransactionAspectSupport.determineTransactionManager(TransactionAspectSupport.java:370)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:271)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodIntercceptor.invoke(CrudMethodMetadataPostProcessor.java:122)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy20.save(Unknown Source)
at org.fxbird.springjpa.service.DepartmentServiceImpl.addDeptAndEmp(DepartmentServiceImpl.java:47)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
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.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy24.addDeptAndEmp(Unknown Source)
at org.fxbird.springjpa.App.main(App.java:15)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:365)
at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:331)
at org.springframework.transaction.interceptor.TransactionAspectSupport.determineTransactionManager(TransactionAspectSupport.java:370)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:271)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.dao.support.PersistenceExceptionTranslationInterceptor.invoke(PersistenceExceptionTranslationInterceptor.java:136)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.data.jpa.repository.support.CrudMethodMetadataPostProcessor$CrudMethodMetadataPopulatingMethodIntercceptor.invoke(CrudMethodMetadataPostProcessor.java:122)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.interceptor.ExposeInvocationInterceptor.invoke(ExposeInvocationInterceptor.java:92)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy20.save(Unknown Source)
at org.fxbird.springjpa.service.DepartmentServiceImpl.addDeptAndEmp(DepartmentServiceImpl.java:47)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
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.springframework.aop.support.AopUtils.invokeJoinpointUsingReflection(AopUtils.java:317)
at org.springframework.aop.framework.ReflectiveMethodInvocation.invokeJoinpoint(ReflectiveMethodInvocation.java:190)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:157)
at org.springframework.transaction.interceptor.TransactionInterceptor$1.proceedWithInvocation(TransactionInterceptor.java:99)
at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:281)
at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:96)
at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
at com.sun.proxy.$Proxy24.addDeptAndEmp(Unknown Source)
at org.fxbird.springjpa.App.main(App.java:15)
我的配置:
<?xml version="1.0" encoding="UTF-8"?> <beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:context="http://www.springframework.org/schema/context" xmlns:jdbc="http://www.springframework.org/schema/jdbc" xmlns:tx="http://www.springframework.org/schema/tx" xmlns:jpa="http://www.springframework.org/schema/data/jpa" xmlns:aop="http://www.springframework.org/schema/aop" xsi:schemaLocation="http://www.springframework.org/schema/jdbc http://www.springframework.org/schema/jdbc/spring-jdbc.xsd http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd http://www.springframework.org/schema/tx http://www.springframework.org/schema/tx/spring-tx.xsd http://www.springframework.org/schema/data/jpa http://www.springframework.org/schema/data/jpa/spring-jpa.xsd http://www.springframework.org/schema/context http://www.springframework.org/schema/context/spring-context.xsd http://www.springframework.org/schema/aop http://www.springframework.org/schema/aop/spring-aop.xsd"> <aop:config> <aop:pointcut id="serviceOperation" expression="execution(* org.fxbird.springjpa.service.*ServiceImpl.*(..))"/> <aop:advisor pointcut-ref="serviceOperation" advice-ref="txAdvice"/> </aop:config> <tx:advice id="txAdvice" transaction-manager="tm1"> <tx:attributes> <tx:method name="find*" read-only="true"/> <tx:method name="count*" propagation="NEVER"/> <tx:method name="*" /> </tx:attributes> </tx:advice> <bean abstract="true" id="baseDS" class="org.apache.commons.dbcp.BasicDataSource" lazy-init="true"> <property name="initialSize" value="3"/> <property name="username" value="root"/> <property name="password" value="root"/> </bean> <bean id="dataSource1" parent="baseDS"> <property name="url"> <value>jdbc:mysql://localhost/company?useUnicode=true&characterEncoding=utf-8</value> </property> </bean> <bean id="dataSource2" parent="baseDS"> <property name="url"> <value>jdbc:mysql://localhost/employee?useUnicode=true&characterEncoding=utf-8</value> </property> </bean> <bean abstract="true" id="baseEmf" class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean"> <property name="packagesToScan" value="org.fxbird.springjpa.model"/> <property name="jpaVendorAdapter"> <bean class="org.springframework.orm.jpa.vendor.EclipseLinkJpaVendorAdapter"/> </property> <property name="jpaProperties"> <props> <prop key="databasePlatform">org.eclipse.persistence.platform.database.MySQLPlatform</prop> <prop key="eclipselink.jdbc.cache-statements">true</prop> <prop key="eclipselink.weaving">false</prop> <prop key="eclipselink.logging.level">FINEST</prop> <prop key="eclipselink.allow-zero-id">true</prop> <!--<prop key="eclipselink.target-server">com.atomikos.eclipselink.platform.AtomikosTransactionController</prop>--> <!--<prop key="eclipselink.external-transaction-controller">true</prop>--> </props> </property> </bean> <bean id="emfCompany" parent="baseEmf"> <property name="dataSource" ref="dataSource1"/> </bean> <bean id="emfEmp" parent="baseEmf"> <property name="dataSource" ref="dataSource2"/> </bean> <bean id="tm1" class="org.springframework.orm.jpa.JpaTransactionManager"> <property name="entityManagerFactory" ref="emfCompany"/> </bean> <bean id="tm2" name="tm2" class="org.springframework.orm.jpa.JpaTransactionManager"> <qualifier value="tm2"/> <property name="entityManagerFactory" ref="emfEmp"/> </bean> <context:component-scan base-package="org.fxbird.springjpa.service" /> <jpa:repositories base-package="org.fxbird.springjpa.repo.company" entity-manager-factory-ref="emfCompany" transaction-manager-ref="tm1"/> <jpa:repositories base-package="org.fxbird.springjpa.repo.emp" entity-manager-factory-ref="emfEmp" transaction-manager-ref="tm2"/> <tx:annotation-driven /> </beans>
后来我找来了书上的例子,却一切正常,仔细对比了代码的不同好几遍,没发现任何异常,头发却快掉了好几十根了。第二天又试了一下,忽然怀疑是不是有可能jar包版本不同导致的,书上的例子用的是spring 4.0.2,而我用的是4.1.4,换成书上的版本一运行果然错误没了,shit,困扰我好几天了,又换成最新的4.1.6,也没有问题,看来就是版本问题了。