当前位置: 首页 > 知识库问答 >
问题:

如何使用Spring@Configuration类配置多个JPA数据源?

卫泉
2023-03-14

我试图使用Spring的@Configuration类在同一应用程序上下文中配置多个JPA实体/事务管理器。

当加载上下文时,Spring很难自动连接bean,因为它们实现了相同的接口

不幸的是,我使用的是遗留代码,因此无法直接自动连接bean并使用@Qualifier注释,这就是为什么我试图使用配置类来完成这项工作。

@Bean声明中,是否有任何方法来限定应该注入哪个Bean?我认为使用直接方法调用就足够了,但它通常会导致以下错误:

NonuniqueBeandDefinitionException:未定义[javax.sql.DataSource]类型的合格bean:应为单个匹配bean,但找到4个

下面是我试图做的一个例子:

@Configuration    
public class ApplicationConfig {

@Bean(name = "transactionManager1")
public PlatformTransactionManager transactionManager1() {
    return new JpaTransactionManager(entityManagerFactory1());
}

@Bean(name = "entityManagerFactory1")
public EntityManagerFactory entityManagerFactory1() {
    ...
    LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
    factory.setDataSource(dataSource1());
    ...
}

@Bean(destroyMethod = "")
@ConfigurationProperties(prefix = "datasource.test1")
public JndiObjectFactoryBean jndiObjectFactoryBean1() {
    return new JndiObjectFactoryBean();
}

@Bean(name = "dataSource1")
public DataSource dataSource1() {
    JndiDataSourceLookup lookup = new JndiDataSourceLookup();
    return lookup.getDataSource(jndiObjectFactoryBean1().getJndiName());
}

@Bean(name = "transactionManager2")
public PlatformTransactionManager transactionManager2() {
    return new JpaTransactionManager(entityManagerFactory2());
}

@Bean(name = "entityManagerFactory2")
public EntityManagerFactory entityManagerFactory2() {
    ...
    LocalContainerEntityManagerFactoryBean factory = new LocalContainerEntityManagerFactoryBean();
    factory.setDataSource(dataSource2());
    ...
}

@Bean(destroyMethod = "")
@ConfigurationProperties(prefix = "datasource.test2")
public JndiObjectFactoryBean jndiObjectFactoryBean2() {
    return new JndiObjectFactoryBean();
}

@Bean(name = "dataSource2")
public DataSource dataSource2() {
    JndiDataSourceLookup lookup = new JndiDataSourceLookup();
    return lookup.getDataSource(jndiObjectFactoryBean2().getJndiName());
}

我想我可以尝试通过Spring上下文的getBean()方法直接注入bean,但是有没有更干净的方法呢?

我对@Primary注释不太熟悉,但根据我读到的内容,我不知道spring在这种情况下会如何自动连接辅助数据源,因为它看起来总是先用@Primary来选择bean。

共有1个答案

郤仰岳
2023-03-14

如果您不能更改注入站点以添加限定符,那么您将不得不基于某些逻辑(您在问题中没有详细说明)创建委托DataSource

像这样的。

@Primary @Bean
public DelegatingDataSource delegatingDataSource(List<DataSource> sources) {
    return new DelegatingDataSource() {
        @Override
        public DataSource getTargetDataSource() {
            // decide which dataSource to delegate to
            return sources.get(0);
        }
    }
}

我使用了DelegatingDataSource,但这可能无法提供您所需的内容。您可能需要更高级地使用某种拦截器/方面来获取调用方的详细信息,以作为数据源选择的基础。

无论实现了什么,您都需要指定一个@主bean并将其用作代理。

 类似资料: