【问题标题】:Java application with Spring and Hibernate upgraded from 3.2.1 to 4.3.2 and 4.2.0 to 5.2.1 throwing error带有 Spring 和 Hibernate 的 Java 应用程序从 3.2.1 升级到 4.3.2 和 4.2.0 到 5.2.1 抛出错误
【发布时间】:2016-12-05 14:41:14
【问题描述】:

应用程序抛出以下错误:

org.springframework.beans.factory.NoUniqueBeanDefinitionException: 否 类型的限定 bean [org.springframework.transaction.PlatformTransactionManager] 是 已定义:预期的单个匹配 bean,但找到了 3 个

您好,我们有一个 webapp,我们升级到上述配置,在 java 8, tomcat 8 上运行。在与数据库的第一次交互(写入事务)时,应用程序会抛出上述错误。

我们使用了 Spring 的 Hibernate Transaction Manager 实现。我们定义了 spring aop 以将 bo 方法 包含在事务中,以及针对某些异常的必要操作(基本上是回滚)的事务建议。

注意:JDK和tomcat也升级了,都是从6升级到8

在升级 Spring、Hibernate、tomcat 和 java 之前,我们在应用程序中具有相同的配置(如下所述),这些配置一直正常运行,甚至在我们遇到此错误时也没有。

每个数据源、会话工厂和事务管理器定义如下 数据源是这样的

session factory configuration
<bean id="sessionFactory1" class="org.springframework.orm.hibernate5.LocalSessionFactoryBean">
    <property name="dataSource" ref="dataSource1"/>
    <property name="mappingResources">
       <list>
          <!-- List of hbm mappings -->
       </list>
    </property>
    <property name="hibernateProperties">
        <props>
            <prop key="hibernate.dialect">${hibernate.dialect}</prop>
            <prop key="hibernate.show_sql">true</prop>
            <prop key="hibernate.generate_statistics">true</prop>
            <prop key="hibernate.format_sql">false</prop>
            <prop key="hibernate.use_sql_comments">false</prop>
            <prop key="hibernate.connection.release_mode">after_transaction</prop>
            <prop key="hibernate.c3p0.timeout">1</prop>
        </props>
    </property>
</bean> 

Transaction manager, transaction advice and aop config
<bean id="transactionManager1" class="org.springframework.orm.hibernate5.HibernateTransactionManager">
    <property name="sessionFactory" ref="sessionFactory1"/>
</bean>
<tx:advice id="defaultTxAdvice1" transaction-manager="transactionManager1">
   <tx:attributes>
      <tx:method name="get*" read-only="true"/>
      <tx:method name="*" rollback-for="com.xyz.platformcore.common.exception.VyasaException"/>
   </tx:attributes>
</tx:advice>

<aop:config>
  <aop:pointcut id="serviceOperation1" expression="execution(* com..*BO.*(..)) || execution(* com..*Bo.*(..)) || execution(* com..*bo.*(..)) || execution(* com.xyz.platformcore..*BO.*(..)) || execution(* com.xyz.framework..*bo.*(..)) || execution(* com.xyz.framework..*Bo.*(..)) || execution(* com.xyz.platformcore..*Bo.*(..)) ||  @annotation(com.xyz.platformcore.common.hibernate.VyasaTransactionAwareHibernateOperation) || within(@com.xyz.platformcore.common.hibernate.VyasaTransactionAwareHibernateOperation *)" />
  <aop:advisor advice-ref="defaultTxAdvice1" pointcut-ref="serviceOperation1"/>
</aop:config>

My dao method

public void invalidateSomeThing() {
    Query query = getSession1().createQuery("update SomeThing set isActive =:isActive");
    query.setParameter("isActive", false);
    query.executeUpdate();
}
getSession1() gives the Session object from SessionFcatory1 which connects to DataSource1

非常感谢任何帮助

【问题讨论】:

  • 您可以尝试将“主要”属性添加到您的 transactionManager1-Bean 吗?看起来 spring 找到了 3 个不同的事务管理器,不知道该选择哪一个。
  • 我担心这可能不起作用,因为例外问题可能会得到解决(我们试过这个)。如果 Spring 必须选择 transactionManager2 并且发生相同的冲突并且它实际上拍摄了 transactionManager1 怎么办?

标签: java spring hibernate aop spring-transactions


【解决方案1】:

请检查一下...“当定义多个事务管理器时,事务管理器缓存无法重新填充”

https://jira.spring.io/browse/SPR-14609

这是 Spring FW 4.3.2 版本中的一个错误。已在 4.3.3 中修复。

问候, --yash

【讨论】:

    【解决方案2】:

    如 Spring 文档中所述:

    NoUniqueBeanDefinitionException

    当 BeanFactory 被要求提供 bean 实例时抛出异常 当只有一个时找到了多个匹配的候选者 预期匹配 bean。

    所以基本上,您拥有三个具有相同标识符和/或名称的 org.springframework.transaction.PlatformTransactionManager 的 Spring “bean”。最终,您可以拥有任意数量的对象,但 Spring 容器必须有一种方法来“识别”它们……通常是通过类型,然后是名称。

    尝试在debug模式下在启动时记录输出;它会一步一步地告诉你正在加载的 bean 是什么以及类似的东西。无论如何,您应该在配置中的某处有三个定义org.springframework.transaction.PlatformTransactionManager

    【讨论】:

    • 我们有三个不同的“bean”,它们都具有不同的名称,但每个 bean 的类型都是相同的 org.springframework.transaction.PlatformTransactionManager
    • 您是否在代码中以编程方式注入它们?如果是这样,您需要通过使用 Spring 的 @Qualifier 或 Java EE 的 @Resource(name="beanName")指定您想要的。我记得在 bean 的定义中还有一个用于 XML 配置的 autowire 属性,可以让你这样做。
    • 不,我们在上面发布的代码中使用基于 XML 的注入。我们没有使用注释驱动的事务,我们需要 3 个相同类型的不同事务来处理三个不同的数据源,因此我怀疑autowire 是否对我们有任何帮助。
    猜你喜欢
    • 2016-12-14
    • 1970-01-01
    • 1970-01-01
    • 2014-03-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多