繁体   English   中英

Spring引导@Qualifier不适用于数据源

[英]Spring boot @Qualifier doesn't work with datasources

我正在使用不同的内存数据源构建具有多个持久性单元的 JPA配置,但配置无法解析实体管理器工厂bean的限定数据源 ,并出现以下错误:

***************************
APPLICATION FAILED TO START
***************************

Description:

Parameter 0 of method emfb in datasources.Application$PersistenceConfiguration required a single bean, but 2 were found:
        - ds1: defined by method 'ds1' in class path resource [datasources/Application$PersistenceConfiguration.class]
        - ds2: defined by method 'ds2' in class path resource [datasources/Application$PersistenceConfiguration.class]


Action:

Consider marking one of the beans as @Primary, updating the consumer to accept multiple beans, or using @Qualifier to identify the bean that should be consumed

这是示例应用程序

package datasources;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.PersistenceContextType;
import javax.sql.DataSource;
import javax.ws.rs.ApplicationPath;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import org.apache.log4j.Logger;
import org.glassfish.jersey.server.ResourceConfig;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.boot.autoconfigure.transaction.jta.JtaAutoConfiguration;
import org.springframework.boot.builder.SpringApplicationBuilder;
import org.springframework.boot.orm.jpa.EntityManagerFactoryBuilder;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.ComponentScan;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Primary;
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
import org.springframework.orm.jpa.LocalContainerEntityManagerFactoryBean;
import org.springframework.stereotype.Component;

@Configuration
@EnableAutoConfiguration(exclude = {
//      HibernateJpaAutoConfiguration.class,
//      DataSourceAutoConfiguration.class
        JtaAutoConfiguration.class
})
@ComponentScan
public class Application {

    public static void main(String[] args) {

        new SpringApplicationBuilder(Application.class)
            .build()
            .run(args);
    }

    @Component
    @Path("/ds")
    public static class DsApi {

        private final static Logger logger = Logger.getLogger(DsApi.class);

        @Autowired(required = false)
        @Qualifier("ds1")
        private DataSource ds;

        @GET
        public String ds() {
            logger.info("ds");
            return ds.toString();
        }
    }

    @Component
    @Path("/em")
    public static class EmApi {

        private final static Logger logger = Logger.getLogger(EmApi.class);

        @PersistenceContext(unitName = "ds2", type = PersistenceContextType.TRANSACTION)
        private EntityManager em;

        @GET
        public String em() {
            logger.info("em");
            return em.toString();
        }
    }

    @Configuration
    @ApplicationPath("/jersey")
    public static class JerseyConfig extends ResourceConfig {
        public JerseyConfig() {
            register(DsApi.class);
            register(EmApi.class);
        }
    }

    @Configuration
    public static class PersistenceConfiguration {

        @Bean
        @Qualifier("ds1")
        public DataSource ds1() {
            return new EmbeddedDatabaseBuilder().build();
        }

        @Bean
        @Qualifier("ds2")
        public DataSource ds2() {
            return new EmbeddedDatabaseBuilder().build();
        }

        @Bean
        @Primary
        @Autowired
        public LocalContainerEntityManagerFactoryBean emfb(@Qualifier("ds1") DataSource ds, EntityManagerFactoryBuilder emfb) {
            return emfb.dataSource(ds)
                    .packages(Application.class)
                    .persistenceUnit("ds1")
                    .build();
        }

        @Bean
        @Autowired
        public LocalContainerEntityManagerFactoryBean emfb2(@Qualifier("ds2") DataSource ds, EntityManagerFactoryBuilder emfb) {
            return emfb.dataSource(ds)
                    .packages(Application.class)
                    .persistenceUnit("ds2")
                    .build();
        }
    }
}

该错误表明在应用程序中的某些点,一个bean正被注入的类型DataSource ,而不是由名称在该点合格。

您在一个位置添加了@Qualifier并不重要。 注射在其他尚未合格的位置失败。 这不是你的错,因为该位置在Spring Boot的DataSourceAutoConfiguration ,您应该能够在堆栈跟踪中看到,在您发布的文件下方。

我建议排除DataSourceAutoConfiguration@SpringBootApplication(exclude = DataSourceAutoConfiguration.class) 否则,此配置仅应用于您创建的@Primary bean。 除非您确切知道它是什么,否则很可能会导致DataSource之间行为的细微和意外差异。

将您的一个DataSource声明为@Primary

你也有2个相同类型的bean - LocalContainerEntityManagerFactoryBean ,声明其中一个@Primary ,如下所示:

@Configuration
public static class PersistenceConfiguration {

        @Bean
        @Primary
        public DataSource ds1() {
            return new EmbeddedDatabaseBuilder().build();
        }

        @Bean
        public DataSource ds2() {
            return new EmbeddedDatabaseBuilder().build();
        }

        @Bean
        @Primary
        @Autowired
        public LocalContainerEntityManagerFactoryBean emfb(@Qualifier("ds1") DataSource ds, EntityManagerFactoryBuilder emfb) {
            return emfb.dataSource(ds)
                    .packages(DemoApplication.class)
                    .persistenceUnit("ds1")
                    .build();
        }

        @Bean
        @Autowired
        public LocalContainerEntityManagerFactoryBean emfb2(@Qualifier("ds2") DataSource ds, EntityManagerFactoryBuilder emfb) {
            return emfb.dataSource(ds)
                    .packages(DemoApplication.class)
                    .persistenceUnit("ds2")
                    .build();
        }
 }

尝试在静态类之外声明数据源bean。 即直接在Application.java中

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM