`

使用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注入的方式。

相关推荐

    Spring声明式事务处理

    文件名为`Spring声明式事务处理-1.mht`到`Spring声明式事务处理-5.mht`,通过阅读这些文件,你将能够深入理解Spring声明式事务处理的各个方面,包括配置、使用场景、最佳实践以及常见问题的解决方法。

    Spring源代码解析(六):Spring声明式事务处理.doc

    Spring 声明式事务处理 Spring 中的事务处理可以分为两种方式:声明式事务处理和编程式事务处理。声明式事务处理通过 AOP 的实现,把事务管理代码作为方面封装到业务代码中,使得事务管理代码和业务代码解藕。这...

    Spring声明式事务

    spring声明式事务实例 可复制修改使用。。。。。。。。。。

    Spring声明式事务配置管理方法

    Spring声明式事务配置管理方法

    spring声明式事务处理demo

    首先,我们要理解Spring事务管理的两种主要方式:编程式事务管理和声明式事务管理。编程式事务管理通常通过AOP(面向切面编程)的TransactionTemplate或PlatformTransactionManager接口直接在代码中控制事务,而声明...

    spring声明式事务管理配置方式

    1. **Spring事务管理器(Transaction Manager)**: - Spring支持多种事务管理器,如DataSourceTransactionManager(用于JDBC事务)和HibernateTransactionManager(用于Hibernate)。事务管理器是负责处理事务的...

    spring声明式事务配置

    根据提供的信息,我们可以深入探讨Spring框架中的声明式事务配置及其多种实现方式。声明式事务管理是一种简化事务管理的方式,它允许开发人员通过配置而非编程来指定事务边界,从而减少了代码的复杂性并提高了可维护...

    Spring 声明式事务和Spring 编程式事务

    Spring 声明式事务和Spring 编程式事务

    spring编程式事务与声明式事务详解

    Spring 提供了多种方式来实现声明式事务管理,例如使用 @Transactional 注解或使用 XML 配置文件。 总结 本文通过详细分析 Spring 的编程式事务管理及声明式事务管理,帮助读者理解事务管理的重要性和实现方式。...

    Spring使用XML配置声明式事务

    这篇博文"Spring使用XML配置声明式事务"详细介绍了如何在Spring中使用XML配置来实现这一功能。 首先,我们需要了解Spring的核心组件之一——ApplicationContext,它是Spring容器的实例,负责管理和装配我们的bean。...

    使用Spring的声明式事务----AOP方式

    本文将深入探讨如何利用Spring的声明式事务来处理业务操作中的数据一致性问题,以及相关源码解析。 首先,我们需要了解Spring的AOP概念。AOP是一种编程范式,它允许程序员定义“切面”,这些切面可以包含业务逻辑的...

    spring+mybatis的声明式事务

    1. **Spring事务管理** Spring提供两种事务管理方式:编程式事务管理和声明式事务管理。编程式事务管理通过编写代码来控制事务的开始、提交、回滚等操作,灵活性高但侵入性强。相比之下,声明式事务管理则更加简洁...

    实验 spring 声明事务

    实验 "Spring 声明事务" 是 Java 高级编程中的一个重要环节,旨在让学生掌握 Spring 框架中声明式事务管理的配置和使用。在实际应用中,事务管理是确保数据一致性、完整性和可靠性的关键组件。Spring 提供了声明式...

    使用Spring的声明式事务----Annotation注解方式

    本篇文章将深入探讨如何使用Spring的声明式事务,特别是通过Annotation注解方式进行设置。 首先,我们需要理解什么是声明式事务。与编程式事务(即手动编写事务管理代码)不同,声明式事务是通过AOP(面向切面编程...

    Spring Boot多数据源(支持Spring声明式事务切换和回滚).pdf

    《Spring Boot多数据源(支持Spring声明式事务切换和回滚)》 Spring Boot多数据源技术是构建高效、灵活的多租户SaaS架构的关键。在本文中,我们将深入探讨如何实现动态数据源切换,支持Spring声明式事务管理,并讨论...

    spring声明式事务.zip

    本文将深入探讨Spring声明式事务的实现机制、优缺点以及如何在实际项目中进行配置和使用。 1. **声明式事务管理概述** 声明式事务管理与编程式事务管理相对,后者需要开发者在代码中显式调用开始、提交、回滚等...

    Spring 2.5整合iBATIS 2.3并使用Spring的声明式事务管理

    本篇将详细介绍如何在Spring 2.5版本中整合iBATIS 2.3,并利用Spring的声明式事务管理,以提升应用程序的稳定性和可维护性。 首先,我们需要了解Spring 2.5和iBATIS 2.3的基本概念。Spring 2.5是Spring框架的一个...

    Spring Data JPA系列4——Spring声明式事务处理与多数据源支持.doc

    Spring 声明式事务处理与多数据源支持 在大部分涉及到数据库操作的项目里面,事务控制、事务处理都是一个无法...通过使用 Spring 声明式事务处理机制,可以简化业务代码中的事务处理逻辑,并提高系统的可靠性和性能。

Global site tag (gtag.js) - Google Analytics