`

使用spring声明式事务出现的奇怪问题

阅读更多

这几天配置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)

 

   我的配置:

   

<?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&amp;characterEncoding=utf-8</value>
        </property>
    </bean>

    <bean id="dataSource2" parent="baseDS">
        <property name="url">
            <value>jdbc:mysql://localhost/employee?useUnicode=true&amp;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,也没有问题,看来就是版本问题了。

 

1
0
分享到:
评论
2 楼 theoffspring 2015-04-20  
酷的飞上天空 写道
报错的信息是:expected single matching bean but found 2: tm2,tm1。
自动注入的时候找到了两个满足条件的bean,导致spring不知道该试用哪个。
改为使用名称注入,或者通过配置文件生命bean注入的方式。


我之前不就是那么做的吗
1 楼 酷的飞上天空 2015-04-19  
报错的信息是:expected single matching bean but found 2: tm2,tm1。
自动注入的时候找到了两个满足条件的bean,导致spring不知道该试用哪个。
改为使用名称注入,或者通过配置文件生命bean注入的方式。

相关推荐

Global site tag (gtag.js) - Google Analytics