2014-10-10 15 views
24

Ich versuche, jedes @Repositories zu verschiedenen DataSource mit Spring Boot und Spring Data JPA zu verbinden. Als Referenz habe ich folgendes verwendet: http://xantorohara.blogspot.com/2013/11/spring-boot-jdbc-with-multiple.html. Hier ist der Code, den ich verwende, um eine ähnliche Lösung mit Spring Data JPA zu implementieren.Spring Boot, Spring Data JPA mit mehreren DataSources

CustomerDbConfig.java (Erste Datenquellenverbindung)

@Configuration 
@EnableJpaRepositories(
     entityManagerFactoryRef = "orderEntityManager", 
     transactionManagerRef = "orderTransactionManager", 
     basePackages = {"com.mm.repository.customer"}) 
public class CustomerDbConfig { 

    @Bean(name = "customerEntityManager") 
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(){ 
     LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); 
     em.setDataSource(dataSource()); 
     em.setPackagesToScan(new String[] {"com.mm.domain.customer"}); 

     JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); 
     em.setJpaVendorAdapter(vendorAdapter); 
     em.setJpaProperties(additionalJpaProperties()); 
     em.setPersistenceUnitName("customerPersistence"); 
     em.setPackagesToScan("com.mm.domain.customer"); 

     return em; 
    } 

    Properties additionalJpaProperties(){ 
     Properties properties = new Properties(); 
     properties.setProperty("hibernate.hbm2ddl.auto", "create-drop"); 
     properties.setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect"); 
     properties.setProperty("hibernate.show_sql", "true"); 

     return properties; 
    } 

    @Bean 
    public DataSource dataSource(){ 
     return DataSourceBuilder.create() 
       .url("jdbc:h2:mem:customer:H2") 
       .driverClassName("org.h2.Driver") 
       .username("sa") 
       .password("") 
       .build(); 
    } 

    @Bean(name = "customerTransactionManager") 
    public PlatformTransactionManager transactionManager(EntityManagerFactory emf){ 
     JpaTransactionManager transactionManager = new JpaTransactionManager(); 
     transactionManager.setEntityManagerFactory(emf); 

     return transactionManager; 
    } 
} 

CustomerDbConfig.java (zweite Datenquelle)

@Configuration 
@EnableJpaRepositories(
     entityManagerFactoryRef = "orderEntityManager", 
     transactionManagerRef = "orderTransactionManager", 
     basePackages = {"com.mm.repository.customer"}) 
public class CustomerDbConfig { 

    @Bean(name = "customerEntityManager") 
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(){ 
     LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); 
     em.setDataSource(dataSource()); 
     em.setPackagesToScan(new String[] {"com.mm.domain.customer"}); 

     JpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); 
     em.setJpaVendorAdapter(vendorAdapter); 
     em.setJpaProperties(additionalJpaProperties()); 
     em.setPersistenceUnitName("customerPersistence"); 
     em.setPackagesToScan("com.mm.domain.customer"); 

     return em; 
    } 

    Properties additionalJpaProperties(){ 
     Properties properties = new Properties(); 
     properties.setProperty("hibernate.hbm2ddl.auto", "create-drop"); 
     properties.setProperty("hibernate.dialect", "org.hibernate.dialect.H2Dialect"); 
     properties.setProperty("hibernate.show_sql", "true"); 

     return properties; 
    } 

    @Bean 
    public DataSource dataSource(){ 
     return DataSourceBuilder.create() 
       .url("jdbc:h2:mem:customer:H2") 
       .driverClassName("org.h2.Driver") 
       .username("sa") 
       .password("") 
       .build(); 
    } 

    @Bean(name = "customerTransactionManager") 
    public PlatformTransactionManager transactionManager(EntityManagerFactory emf){ 
     JpaTransactionManager transactionManager = new JpaTransactionManager(); 
     transactionManager.setEntityManagerFactory(emf); 

     return transactionManager; 
    } 
} 

Customer.java (Modell)

@Entity 
@Table(name = "customer") 
@Data 
@EqualsAndHashCode(exclude = {"id"}) 
public class Customer { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Integer id; 

    @Column(name = "name", nullable = false) 
    private String name; 

    @Column(name = "age", nullable = false) 
    private Integer age; 

.... 

Order.java (Modell)

@Entity 
@Table(name = "order") 
@Data 
@EqualsAndHashCode(exclude = {"id"}) 
public class Order { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Integer id; 

    @Column(name = "code", nullable = false) 
    private Integer code; 

    @Column(name = "quality", nullable = false) 
    private Integer quality; 

...

CustomerRepository.java

public interface CustomerRepository extends JpaRepository<Customer, Integer>{ 

} 

OrderRepository.java

public interface OrderRepository extends JpaRepository<Order, Integer> { 

} 

Schließlich Application.java

@Configuration 
@ComponentScan 
@EnableAutoConfiguration 
public class Application extends SpringApplication{ 

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

     @Bean 
     public ServletRegistrationBean h2Console() { 
      ServletRegistrationBean reg = new ServletRegistrationBean(new WebServlet(), "/console/*"); 
      reg.setLoadOnStartup(1); 
      return reg; 
     } 
} 

Während der folgenden Ausnahmen beginnen geworfen werden:

-10-10 15:45:24.757 ERROR 1549 --- [   main] o.s.boot.SpringApplication    : Application startup failed 

org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'customerTransactionManager' defined in class path resource [com/mm/boot/multidb/CustomerConfig.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [javax.persistence.EntityManagerFactory]: : No qualifying bean of type [javax.persistence.EntityManagerFactory] is defined: expected single matching bean but found 2: customerEntityManager,orderEntityManager; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [javax.persistence.EntityManagerFactory] is defined: expected single matching bean but found 2: customerEntityManager,orderEntityManager 
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:747) 
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:462) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1095) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:990) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475) 
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302) 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:706) 
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:762) 
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482) 
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:109) 
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:691) 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:320) 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:952) 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:941) 
    at com.mm.boot.multidb.Application.main(Application.java:17) 
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [javax.persistence.EntityManagerFactory] is defined: expected single matching bean but found 2: customerEntityManager,orderEntityManager 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:974) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:862) 
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:811) 
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:739) 
    ... 18 common frames omitted 

Exception in thread "main" org.springframework.beans.factory.UnsatisfiedDependencyException: Error creating bean with name 'customerTransactionManager' defined in class path resource [com/mm/boot/multidb/CustomerConfig.class]: Unsatisfied dependency expressed through constructor argument with index 0 of type [javax.persistence.EntityManagerFactory]: : No qualifying bean of type [javax.persistence.EntityManagerFactory] is defined: expected single matching bean but found 2: customerEntityManager,orderEntityManager; nested exception is org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [javax.persistence.EntityManagerFactory] is defined: expected single matching bean but found 2: customerEntityManager,orderEntityManager 
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:747) 
    at org.springframework.beans.factory.support.ConstructorResolver.instantiateUsingFactoryMethod(ConstructorResolver.java:462) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.instantiateUsingFactoryMethod(AbstractAutowireCapableBeanFactory.java:1095) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBeanInstance(AbstractAutowireCapableBeanFactory.java:990) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.doCreateBean(AbstractAutowireCapableBeanFactory.java:504) 
    at org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory.createBean(AbstractAutowireCapableBeanFactory.java:475) 
    at org.springframework.beans.factory.support.AbstractBeanFactory$1.getObject(AbstractBeanFactory.java:302) 
    at org.springframework.beans.factory.support.DefaultSingletonBeanRegistry.getSingleton(DefaultSingletonBeanRegistry.java:228) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.doGetBean(AbstractBeanFactory.java:298) 
    at org.springframework.beans.factory.support.AbstractBeanFactory.getBean(AbstractBeanFactory.java:193) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.preInstantiateSingletons(DefaultListableBeanFactory.java:706) 
    at org.springframework.context.support.AbstractApplicationContext.finishBeanFactoryInitialization(AbstractApplicationContext.java:762) 
    at org.springframework.context.support.AbstractApplicationContext.refresh(AbstractApplicationContext.java:482) 
    at org.springframework.boot.context.embedded.EmbeddedWebApplicationContext.refresh(EmbeddedWebApplicationContext.java:109) 
    at org.springframework.boot.SpringApplication.refresh(SpringApplication.java:691) 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:320) 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:952) 
    at org.springframework.boot.SpringApplication.run(SpringApplication.java:941) 
    at com.mm.boot.multidb.Application.main(Application.java:17) 
Caused by: org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [javax.persistence.EntityManagerFactory] is defined: expected single matching bean but found 2: customerEntityManager,orderEntityManager 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:974) 
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:862) 
    at org.springframework.beans.factory.support.ConstructorResolver.resolveAutowiredArgument(ConstructorResolver.java:811) 
    at org.springframework.beans.factory.support.ConstructorResolver.createArgumentArray(ConstructorResolver.java:739) 
    ... 18 more 

Voll Code für die Probe kann auf GitHub (https://github.com/tonym2105/samples/tree/master/boot-multidb-sample)

finden

Vielen Dank im Voraus für die Hilfe.

+0

Zunächst einmal tun Sie viel zu viel Konfiguration, die Spring Boot für Sie tun kann. Check out http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-two-datasources – geoand

+0

Haben Sie immer noch das gleiche Problem? Ich frage, weil ich Ihren Code ausgecheckt und es funktioniert für mich mit geringfügigen Änderungen (nichts mit dem Fehler zu tun, den Sie in der Frage angeben) – geoand

+0

Es funktioniert nur nach dem Festlegen von spring.jpa.open_in_view = false in den Eigenschaften der Anwendung, wie vorgeschlagen in der Antwort unten. – tonym2105

Antwort

2

Ich habe den Quellcode überprüft, den Sie auf GitHub bereitgestellt haben. Es gab mehrere Fehler/Tippfehler in der Konfiguration.

In CustomerDbConfig/OrderDbConfig sollten Sie customerEntityManager beziehen und Pakete sollten in der bisherigen Pakete zeigen:

@Configuration 
@EnableJpaRepositories(
    entityManagerFactoryRef = "customerEntityManager", 
    transactionManagerRef = "customerTransactionManager", 
    basePackages = {"com.mm.boot.multidb.repository.customer"}) 
public class CustomerDbConfig { 

Die Pakete in customerEntityManager und orderEntityManager scannen waren beide nicht auf korrektem Paket zeigt:

em.setPackagesToScan("com.mm.boot.multidb.model.customer"); 

Auch die Injektion der richtigen EntityManagerFactory hat nicht funktioniert. Es sollte sein:

@Bean(name = "customerTransactionManager") 
public PlatformTransactionManager transactionManager(EntityManagerFactory customerEntityManager){ 

} 

Das obige verursachte das Problem und die Ausnahme. Während Sie den Namen in einer @Bean-Methode angeben, sind Sie sicher, dass Sie eine korrekte EMF-Injektion erhalten.

Das letzte, was ich getan habe, war die automatische Konfiguration von JpaRepositories zu deaktivieren:

@EnableAutoConfiguration(exclude = JpaRepositoriesAutoConfiguration.class) 

Und mit allen Fixes die Anwendung gestartet wird, wie Sie wahrscheinlich erwarten!

+0

Zuerst, danke. Ich bekomme jetzt eine "org.springframework.beans.factory.NoUniqueBeanDefinitionException: Keine qualifizierende Bean vom Typ [javax.persistence.EntityManagerFactory] definiert ist: erwartet einzelne übereinstimmende Bean aber gefunden 2: customerEntityManager, OrderEntityManager" Ausnahme. GitHib wurde mit den vorgeschlagenen Änderungen aktualisiert. – tonym2105

+1

Die automatische Konfiguration von EntityManagerInViewInterceptor verursacht dies. Sie sollten es einfach deaktivieren können, indem Sie in den Anwendungseigenschaften spring.jpa.open_in_view = false angeben. –

+0

Das funktioniert. Aber was bedeutet die Deaktivierung der Immobilie? Danke nochmal für die Hilfe. – tonym2105

33

Es gibt eine andere Möglichkeit, mehrere Datenquellen mithilfe von @EnableAutoConfiguration und application.properties zu erstellen.

Setzen Sie im Grunde mehrere Datenquellen-Konfigurationsinformationen in application.properties und generieren Sie das Standard-Setup (dataSource und entityManagerFactory) automatisch für die erste dataSource mit @EnableAutoConfiguration. Erstellen Sie für die nächste dataSource jedoch dataSource, entityManagerFactory und transactionManager manuell über die Info aus der Eigenschaftendatei.

Unten ist mein Beispiel zum Einrichten von zwei DataSources. Die erste dataSource wird von @EnableAutoConfiguration eingerichtet, die nur für eine Konfiguration zugewiesen werden kann, nicht für mehrere. Und das generiert "transactionManager" von DataSourceTransactionManager, die StandardtransaktionsManager von der Annotation generiert aussieht. Ich habe jedoch gesehen, dass die Transaktion nicht im Thread aus dem geplanten Thread-Pool beginnt, sondern nur für den Standard-DataSourceTransactionManager und auch dann, wenn mehrere Transaktionsmanager vorhanden sind. Also erstelle ich transactionManager manuell von JpaTransactionManager auch für die erste dataSource mit Zuordnung 'Bean' transactionManager 'und Standard-EntityManagerFactory. Dieser JpaTransactionManager für die erste dataSource behebt das seltsame Transaktionsproblem im Thread von ScheduledThreadPool.

Update für Frühling Stiefel 1.3.0.RELEASE

fand ich meine vorherige Konfiguration mit @EnableAutoConfiguration für Standard-Datasource Problem hat EntityManagerFactory mit Frühlings-Boot-Version 1.3 auf der Suche. Vielleicht wird der Standard entityManagerFactory nicht von @EnableAutoConfiguration generiert, nachdem ich meinen eigenen transactionManager eingeführt habe. So jetzt erstelle ich EntityManagerFactory von mir. Daher muss ich @EntityScan nicht verwenden. So sieht es aus, dass ich mehr und mehr aus dem Setup von @EnableAutoConfiguration bekomme.

Die zweite dataSource wird ohne @EnableAutoConfiguration eingerichtet und erstellt "anderenTransactionManager" manuell.

Da es mehr von transaction PlatformTransactionManager erstreckt, sollten wir festlegen, welche transaction auf jeder @Transactional Anmerkung verwenden

Standard Repository Config

@Configuration 
@EnableTransactionManagement 
@EnableAutoConfiguration 
@EnableJpaRepositories(
     entityManagerFactoryRef = "entityManagerFactory", 
     transactionManagerRef = "transactionManager", 
     basePackages = {"com.mysource.repository"}) 
public class RepositoryConfig { 
    @Autowired 
    JpaVendorAdapter jpaVendorAdapter; 

    @Autowired 
    DataSource dataSource; 

    @Bean(name = "entityManager") 
    public EntityManager entityManager() { 
     return entityManagerFactory().createEntityManager(); 
    } 

    @Primary 
    @Bean(name = "entityManagerFactory") 
    public EntityManagerFactory entityManagerFactory() { 
     LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean(); 
     emf.setDataSource(dataSource); 
     emf.setJpaVendorAdapter(jpaVendorAdapter); 
     emf.setPackagesToScan("com.mysource.model"); 
     emf.setPersistenceUnitName("default"); // <- giving 'default' as name 
     emf.afterPropertiesSet(); 
     return emf.getObject(); 
    } 

    @Bean(name = "transactionManager") 
    public PlatformTransactionManager transactionManager() { 
     JpaTransactionManager tm = new JpaTransactionManager(); 
     tm.setEntityManagerFactory(entityManagerFactory()); 
     return tm; 
    } 
} 

ein anderes Repository Config

@Configuration 
@EnableTransactionManagement 
@EnableJpaRepositories(
     entityManagerFactoryRef = "anotherEntityManagerFactory", 
     transactionManagerRef = "anotherTransactionManager", 
     basePackages = {"com.mysource.anothersource.repository"}) 
public class AnotherRepositoryConfig { 
    @Autowired 
    JpaVendorAdapter jpaVendorAdapter; 

    @Value("${another.datasource.url}") 
    private String databaseUrl; 

    @Value("${another.datasource.username}") 
    private String username; 

    @Value("${another.datasource.password}") 
    private String password; 

    @Value("${another.dataource.driverClassName}") 
    private String driverClassName; 

    @Value("${another.datasource.hibernate.dialect}") 
    private String dialect; 

    public DataSource dataSource() { 
     DriverManagerDataSource dataSource = new DriverManagerDataSource(databaseUrl, username, password); 
     dataSource.setDriverClassName(driverClassName); 
     return dataSource; 
    } 

    @Bean(name = "anotherEntityManager") 
    public EntityManager entityManager() { 
     return entityManagerFactory().createEntityManager(); 
    } 

    @Bean(name = "anotherEntityManagerFactory") 
    public EntityManagerFactory entityManagerFactory() { 
     Properties properties = new Properties(); 
     properties.setProperty("hibernate.dialect", dialect); 

     LocalContainerEntityManagerFactoryBean emf = new LocalContainerEntityManagerFactoryBean(); 
     emf.setDataSource(dataSource()); 
     emf.setJpaVendorAdapter(jpaVendorAdapter); 
     emf.setPackagesToScan("com.mysource.anothersource.model"); // <- package for entities 
     emf.setPersistenceUnitName("anotherPersistenceUnit"); 
     emf.setJpaProperties(properties); 
     emf.afterPropertiesSet(); 
     return emf.getObject(); 
    } 

    @Bean(name = "anotherTransactionManager") 
    public PlatformTransactionManager transactionManager() { 
     return new JpaTransactionManager(entityManagerFactory()); 
    } 
} 

Anwendung. Eigenschaften

# database configuration 
spring.datasource.url=jdbc:h2:file:~/main-source;AUTO_SERVER=TRUE 
spring.datasource.username=sa 
spring.datasource.password= 
spring.datasource.driver-class-name=org.h2.Driver 
spring.datasource.continueOnError=true 
spring.datasource.initialize=false 

# another database configuration 
another.datasource.url=jdbc:sqlserver://localhost:1433;DatabaseName=another; 
another.datasource.username=username 
another.datasource.password= 
another.datasource.hibernate.dialect=org.hibernate.dialect.SQLServer2008Dialect 
another.datasource.driverClassName=com.microsoft.sqlserver.jdbc.SQLServerDriver 

Wählen Sie die richtige für transaction @Transactional Anmerkung

Dienst für die erste Datenquelle

@Service("mainService") 
@Transactional("transactionManager") 
public class DefaultDataSourceServiceImpl implements DefaultDataSourceService  
{ 

    // 

} 

-Service für eine andere Datenquelle

@Service("anotherService") 
@Transactional("anotherTransactionManager") 
public class AnotherDataSourceServiceImpl implements AnotherDataSourceService 
{ 

    // 

} 
+0

Sorry, das war ein Tippfehler meinerseits. Ich musste ein paar Dinge umbenennen und das habe ich vermisst. Das ist nicht das Problem, aber danke für Ihre Bemühungen. – Drew1208

+0

Das hat mich gerettet! Wollte hinzufügen, dass, wenn es wörtlich folgt, dies bei * 1.5.2.RELEASE * mit Erfolg funktioniert. – Brian

6

Hier ist meine Lösung. Basis auf Spring-Boot.1.2.5.RELEASE.

application.properties

first.datasource.driver-class-name=com.mysql.jdbc.Driver 
first.datasource.url=jdbc:mysql://127.0.0.1:3306/test 
first.datasource.username= 
first.datasource.password= 
first.datasource.validation-query=select 1 

second.datasource.driver-class-name=com.mysql.jdbc.Driver 
second.datasource.url=jdbc:mysql://127.0.0.1:3306/test2 
second.datasource.username= 
second.datasource.password= 
second.datasource.validation-query=select 1 

DataSourceConfig.java

@Configuration 
public class DataSourceConfig { 
    @Bean 
    @Primary 
    @ConfigurationProperties(prefix="first.datasource") 
    public DataSource firstDataSource() { 
     DataSource ds = DataSourceBuilder.create().build(); 
     return ds; 
    } 

    @Bean 
    @ConfigurationProperties(prefix="second.datasource") 
    public DataSource secondDataSource() { 
     DataSource ds = DataSourceBuilder.create().build(); 
     return ds; 
    } 
} 
+1

Wie verweisen Sie darauf? Ich bin so weit gekommen, aber ich weiß nicht, wie ich die zweite Datenquelle über JPA "beschwören" soll. Ich dachte, es wäre entweder in der Entity Annotation oder Query Parameter oder etwas. –

+1

so. '@' Autowired '@' Qualifier ("firstDataSource") private DataSource firstDataSource; '@' Autowired '@' Qualifier ("secondDataSource") private DataSource secondDataSource; – david

-2

weiß nicht, warum, aber es funktioniert. Zwei Konfigurationen sind gleich, nur ändern Sie xxx zu Ihrem Namen.

@Configuration 
@EnableTransactionManagement 
@EnableJpaRepositories(
    entityManagerFactoryRef = "xxxEntityManager", 
    transactionManagerRef = "xxxTransactionManager", 
    basePackages = {"aaa.xxx"}) 
public class RepositoryConfig { 
@Autowired 
private Environment env; 

@Bean 
@Primary 
@ConfigurationProperties(prefix="datasource.xxx") 
public DataSource xxxDataSource() { 
    return DataSourceBuilder.create().build(); 
} 

@Bean 
public LocalContainerEntityManagerFactoryBean xxxEntityManager() { 
    LocalContainerEntityManagerFactoryBean em = new LocalContainerEntityManagerFactoryBean(); 
    em.setDataSource(xxxDataSource()); 
    em.setPackagesToScan(new String[] {"aaa.xxx"}); 

    HibernateJpaVendorAdapter vendorAdapter = new HibernateJpaVendorAdapter(); 
    em.setJpaVendorAdapter(vendorAdapter); 
    HashMap<String, Object> properties = new HashMap<String, Object>(); 
    properties.put("hibernate.show_sql", env.getProperty("hibernate.show_sql")); 
    properties.put("hibernate.hbm2ddl.auto", env.getProperty("hibernate.hbm2ddl.auto")); 
    properties.put("hibernate.dialect", env.getProperty("hibernate.dialect")); 
    em.setJpaPropertyMap(properties); 

    return em; 
} 

@Bean(name = "xxxTransactionManager") 
public PlatformTransactionManager xxxTransactionManager() { 
    JpaTransactionManager tm = new JpaTransactionManager(); 
    tm.setEntityManagerFactory(xxxEntityManager().getObject()); 
    return tm; 
} 

}

+0

datasource.xxx.url = datasource.xxx.username = datenquelle.xxx.password = datasource.xxx.driver-class-name = com.mysql.jdbc.Driver – dongwenting

1

dank der Antworten von Steve Park und Rafal Borowiec bekam ich meinen Code arbeiten, aber ich hatte ein Problem: die DriverManagerDataSource ist eine „einfache“ Implementierung und macht Sie keinen geben ConnectionPool (überprüfen Sie http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/jdbc/datasource/DriverManagerDataSource.html).

Daher habe ich die Funktionen ersetzt, die die DataSource für die secondDB zurückgibt.

public DataSource <secondaryDB>DataSource() { 
    // use DataSourceBuilder and NOT DriverManagerDataSource 
    // as this would NOT give you ConnectionPool 
    DataSourceBuilder dataSourceBuilder = DataSourceBuilder.create(); 
    dataSourceBuilder.url(databaseUrl); 
    dataSourceBuilder.username(username); 
    dataSourceBuilder.password(password); 
    dataSourceBuilder.driverClassName(driverClassName); 
    return dataSourceBuilder.build(); 
} 

Auch, wenn Sie tun, um die EntityManager als solche nicht benötigen, können Sie sowohl die entityManager() und die @Bean Anmerkung entfernen können.

Außerdem möchten Sie möglicherweise die basePackages-Annotation Ihrer Konfigurationsklasse entfernen: die Pflege mit dem factoryBean.setPackagesToScan() Aufruf ist ausreichend.

Verwandte Themen