具有两个JPA数据库的Spring启动webapp

时间:2014-09-05 09:09:55

标签: spring jpa

我想使用最新版本的spring-batch-admin-manager(v.1.3.0)将现有的spring批处理作业迁移到Spring-Boot webapp。

@Configuration
@EnableAutoConfiguration(exclude = { BatchAutoConfiguration.class, DataSourceAutoConfiguration.class, WebMvcAutoConfiguration.class })
@Import(MainConfiguration.class) @EnableTransactionManagement
public class BatchAdmin extends SpringBootServletInitializer {

  public static void main(String[] args) {
    SpringApplication.run(BatchAdmin.class, args);
  } 
  // ...
}      

@Configuration @ComponentScan("com.company.package*")
@Import({ ServletConfiguration.class, WebappConfiguration.class })
public class MainConfiguration {}

@Configuration
@ImportResource("classpath:/org/springframework/batch/admin/web/resources/servlet-config.xml")
public class ServletConfiguration {}

@Configuration
@ImportResource({ "classpath:/org/springframework/batch/admin/web/resources/webapp-config.xml"
                 ,"classpath:persistence-context.xml" })
public class WebappConfiguration {}

在我的persistence.xml我配置了两个数据源,使用了两个PlatformTransactionManager个实例。 显然,spring-boot默认情况下无法处理这种情况。

Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [org.springframework.transaction.PlatformTransactionManager] is defined: expected single matching bean but found 2: transactionManager,osm.transactionManager
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.getBean(DefaultListableBeanFactory.java:313)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.determineTransactionManager(TransactionAspectSupport.java:337)
    at org.springframework.transaction.interceptor.TransactionAspectSupport.invokeWithinTransaction(TransactionAspectSupport.java:252)
    at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:95)
    at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:179)
    at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:207)
    //...

任何想法如何覆盖spring-boot默认值,以便我可以一起使用两个数据源?

编辑:奇怪的是,尽管定义了两个不同的JpaTransactionManager bean,但事务方面支持似乎没有bean的名称

<bean id="osm.transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="osm.entityManagerFactory" />
</bean>

<tx:advice id="txAdvice" transaction-manager="osm.transactionManager">
    <tx:attributes>
        <tx:method name="*" />
    </tx:attributes>
</tx:advice>

<aop:config>
    <aop:pointcut id="osmServiceOperation"
        expression="execution(* com.company.osm.service.spec..*Service.*(..))" />
    <aop:advisor advice-ref="txAdvice" pointcut-ref="osmServiceOperation" />
</aop:config>

<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager">
    <property name="entityManagerFactory" ref="entityManagerFactory" />
</bean>

beanFactory的getBean方法抛出错误:

protected PlatformTransactionManager determineTransactionManager(TransactionAttribute txAttr) {
    // ...
    else if (this.transactionManagerBeanName != null) { <-- Should go here!
        return this.beanFactory.getBean(this.transactionManagerBeanName, PlatformTransactionManager.class);
    }
    else {
        return this.beanFactory.getBean(PlatformTransactionManager.class); <-- Goes here!
    }
}

1 个答案:

答案 0 :(得分:0)

您必须手动配置数据源:

        @Bean
        public DataSource dataSource1() {
                DriverManagerDataSource dataSource = new DriverManagerDataSource();

                dataSource.setDriverClassName(env.getRequiredProperty(PROPERTY_NAME_DATABASE_DRIVER));
                dataSource.setUrl(env.getRequiredProperty(PROPERTY_NAME_DATABASE_URL));
                dataSource.setUsername(env.getRequiredProperty(PROPERTY_NAME_DATABASE_USERNAME));
                dataSource.setPassword(env.getRequiredProperty(PROPERTY_NAME_DATABASE_PASSWORD));

                return dataSource;
        }

            @Bean
            public DataSource dataSource2() {
                   ...

                    return dataSource;
            }

这样,由spring自动配置的数据源将不再可用。

如果您自动装配数据源,请小心。您必须使用限定符来指定应使用哪一个。