我使用不同的内存数据源构建具有多个持久性单元的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();
}
}
}
答案 0 :(得分:4)
错误表明,在应用程序的某个时刻,某个bean正在按类型DataSource
注入,而且此时没有通过名称限定。
您在一个位置添加了@Qualifier
并不重要。在一些尚未合格的其他位置注入失败。这不是你的错,因为那个位置在Spring Boot的DataSourceAutoConfiguration
中你应该能够在你的堆栈跟踪中看到,在你发布的那一块下方。
我建议排除DataSourceAutoConfiguration
,即@SpringBootApplication(exclude = DataSourceAutoConfiguration.class)
。否则,此配置仅应用于您创建的bean @Primary
。除非您确切知道这是什么,否则可能会导致DataSource
之间行为的细微和意外差异。
答案 1 :(得分:3)
将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();
}
}
答案 2 :(得分:0)
尝试在静态类之外声明数据源bean。我直接在Application.java
中