1

我有一个带有两个 Hibernate 数据源的 Spring Web 应用程序,它们由两个单独的事务管理器管理。数据源是完全独立的,模式方面的。此配置通过了所有单元测试和集成测试,但是当我在 Jetty 中部署它时,存储库操作失败,并出现以下异常:

org.springframework.beans.factory.NoSuchBeanDefinitionException: No bean named my_transactionManager1' is defined: No unique PlatformTransactionManager bean found for qualifier 'my_transactionManager1'
at org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils.qualifiedBeanOfType(BeanFactoryAnnotationUtils.java:84)
at org.springframework.beans.factory.annotation.BeanFactoryAnnotationUtils.qualifiedBeanOfType(BeanFactoryAnnotationUtils.java:55)
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.aop.framework.Cglib2AopProxy$DynamicAdvisedInterceptor.intercept(Cglib2AopProxy.java:625)
at my.controller.Class$$EnhancerByCGLIB$$3976e5ef.myMethodCall(<generated>)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)

持久性.xml

<persistence-unit name="pu1">
<properties>
    <property name="hibernate.dialect" value="${hibernate.dialect}" />
    <property name="hibernate.connection.url" value="${network.db.url}" />
    <property name="hibernate.connection.driver_class" value="${hibernate.connection.driver_class}" />
    <property name="hibernate.connection.username" value="{db.username}" />
    <property name="hibernate.connection.password" value="{db.password}" />
    <property name="hibernate.enable_lazy_load_no_trans" value="true"/>
    <property name="hibernate.hbm2ddl.auto" value="${hibernate.hbm2ddl.auto}" />
    <property name="hibernate.show_sql" value="false" />
</properties>

查看日志,两个数据源的行为似乎都很正常(直到发生此错误)。以下是应用程序上下文:

<?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: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:context="http://www.springframework.org/schema/context"
    xsi:schemaLocation="http://www.springframework.org/schema/jdbc
    http://www.springframework.org/schema/jdbc/spring-jdbc-3.0.xsd
    http://www.springframework.org/schema/beans
    http://www.springframework.org/schema/beans/spring-beans-3.0.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">



    <tx:annotation-driven transaction-manager="my_transactionManager1" />
    <context:component-scan base-package="com.my.package"/>
    <jpa:repositories
        base-package="com.my.package" entity-manager-factory-ref="my_entityManagerFactory" transaction-manager-ref="my_transactionManager1">
    </jpa:repositories>
    <bean id="my_dataSource1" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
        <property name="driverClassName" value="com.mysql.jdbc.Driver"/>
        <property name="url" value="${my.db1.url}"/>
        <property name="username" value="${db1.username}"/>
        <property name="password" value="${db1.password}"/>
    </bean>

    <bean id="my_entityManagerFactory1"
        class="org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean">
        <property name="persistenceUnitName" value="pu1" />
        <property name="dataSource" ref="my_dataSource1" />
        <property name="jpaVendorAdapter">
            <bean class="org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter">
                <property name="databasePlatform" value="${hibernate.dialect}"/>
                <property name="generateDdl" value="false" />
                <property name="database" value="HSQL"/>
            </bean>
        </property>
        <property name="jpaProperties">
            <props>
                <prop key="hibernate.dialect">${hibernate.dialect}</prop>
            </props>
        </property>
    </bean>

    <bean id="my_transactionManager1" class="org.springframework.orm.jpa.JpaTransactionManager">
        <property name="entityManagerFactory" ref="my_entityManagerFactory1" />
        <property name="dataSource" ref="my_dataSource1" />
        <qualifier value="my_transactionManager1"/>
        <property name="persistenceUnitName" value="pu1"/>
    </bean>
</beans>

我试图注入 TransactionManager 的服务类:

Service
@Transactional(value="my_transactionManager1")
@PersistenceContext(unitName = "pu1", name="my_entityManagerFactory1")
public class MyServiceClass{

@Autowired
private Field myField

@Resource(name="my_transactionManager1")
private JpaTransactionManager my_transactionManager1;

/**
* Public no-arg constructor for bean initialization
*/
public MyServiceClass() {}

/**
* Protected IOC constructor for testing
*
* @param resultsService
*/
protected MyServiceClass(Field myField) {
this.myField = myField;
}

我尝试了很多不同的方法来解决这个问题。对于这种情况,经常建议的一件事是单个 JTA XA TransactionManager,但我想避免这种情况,至少在第一次通过时。建议的另一件事是使用 AbstractDataRoutingSource,但我也不想这样做。我的方法似乎站得住脚(如果不是最优的话),因为测试正在通过并且应用程序部署没有错误。这是我的 web.xml(对不起,冗长的帖子):

<?xml version="1.0" encoding="UTF-8"?>
<web-app id="site" xmlns="http://java.sun.com/xml/ns/javaee" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
    xsi:schemaLocation="http://java.sun.com/xml/ns/javaee http://java.sun.com/xml/ns/javaee/web-app_2_5.xsd"
    version="2.5">

    <context-param>
        <param-name>contextConfigLocation</param-name>
        <param-value>
            classpath:my-first-context-file.xml,
            classpath:a-few-other-config-files.xml,
        </param-value>
    </context-param>

    <listener>
        <listener-class>
            org.springframework.web.context.ContextLoaderListener
        </listener-class>


    <servlet>
        <servlet-name>MyServeletName</servlet-name>
        <servlet-class>
            com.sun.jersey.spi.spring.container.servlet.SpringServlet
        </servlet-class>
        <init-param>
            <param-name>
                com.sun.jersey.config.property.packages
            </param-name>
            <param-value>com.my.package</param-value>
        </init-param>
        <init-param>
            <param-name>com.sun.jersey.api.json.POJOMappingFeature</param-name>
            <param-value>true</param-value>
        </init-param>
        <load-on-startup>1</load-on-startup>
    </servlet>

    </load-on-startup>
    </servlet>

    <!--More servlets -->

    <!-- Servlet mapping stuff -->


</web-app>

任何帮助都将不胜感激。

4

2 回答 2

0

确保您拥有唯一的 bean 标识。似乎您有 2 个 id="my_entityManagerFactory1" 的 transactionManager bean 无论如何,您应该添加到注释传播值:@Transactional(propagation=Propagation.REQUIRED, value="my_entityManagerFactory1")

类似的问题(2个数据库中的一个实体)我通过继承解决了:

    @MappedSuperclass
public class User{
    private String name;
    private String surname;
    private String login;
    private String password;
}

@Entity
public class Employee extends User{
    //....
}
@Entity
public class CLient extends User{
    //...
}

Employee 和 Client 类位于实体包的不同子包中。一个 sessionFaction 扫描了第一个子包,另一个 sessionFactory 扫描了第二个。我有两个带有 @Transaction 注释的服务,像上面一样,并通过一个管理器类对两个数据库进行了搜索。在应用程序中,我只使用了用户实体

于 2015-07-18T13:07:25.707 回答
-1

我通过将两个数据库合二为一来“解决”了这个问题。

于 2013-07-27T20:49:44.240 回答