Spring Boot,使用多个数据源的Spring Data JPA

51
我正在尝试使用Spring Boot和Spring Data JPA将每个@Repository连接到不同的DataSource。我参考了http://xantorohara.blogspot.com/2013/11/spring-boot-jdbc-with-multiple.html,并尝试使用以下代码实现类似的解决方案。下面是我使用的代码: CustomerDbConfig.java(第一个数据源连接)
@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 (第二个数据源)

@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 (模型)

@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(模型)

@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> {

}

最后,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;
        }
}

启动时会抛出以下异常:

-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

可以在GitHub上找到示例的完整代码(https://github.com/tonym2105/samples/tree/master/boot-multidb-sample)。

提前感谢您的帮助。


首先,您正在进行太多的配置,而 Spring Boot 可以为您完成。请查看 http://docs.spring.io/spring-boot/docs/current/reference/htmlsingle/#howto-two-datasources。 - geoand
你是否仍然遇到相同的问题?我问这个是因为我检查了你的代码,做了一些小改动后在我的机器上可以工作(与你在问题中提到的错误无关)。 - geoand
只有在应用程序属性中设置spring.jpa.open_in_view = false,才可以像下面的答案建议的那样正常工作。 - tonym2105
6个回答

48

使用@EnableAutoConfiguration和application.properties可以实现多数据源配置。将多个dataSource配置信息放在application.properties中,通过@EnableAutoConfiguration为第一个dataSource自动生成默认设置(dataSource和entityManagerFactory)。对于下一个dataSource,需要手动根据属性文件信息创建dataSource、entityManagerFactory和transactionManager。

以下是我设置两个数据源的示例。第一个dataSource是由@EnableAutoConfiguration设置的,它只能分配给一个配置,不能分配给多个配置。它会生成一个由DataSourceTransactionManager生成的“transactionManager”,看起来像是注释生成的默认transactionManager。但是,我发现当默认的DataSourceTransactionManager遇到线程池中的线程时,事务没有开始,还有当有多个事务管理器时也出现了问题。因此,我为第一个dataSource手动创建了一个名为“transactionManager”的bean,并分配默认的entityManagerFactory,使用JpaTransactionManager。第一个dataSource的JpaTransactionManager可以解决来自ScheduledThreadPool的线程上的奇怪的事务问题。

更新Spring Boot 1.3.0.RELEASE版本

我发现在Spring Boot 1.3版本中,使用@EnableAutoConfiguration设置默认的dataSource时存在找不到entityManagerFactory的问题。可能是因为在我引入自己的transactionManager后,@EnableAutoConfiguration没有生成默认的entityManagerFactory。所以现在我自己创建entityManagerFactory,不需要使用@EntityScan。看起来我越来越摆脱@EnableAutoConfiguration的设置了。

第二个dataSource是在没有@EnableAutoConfiguration的情况下设置的,并通过手动方式创建"anotherTransactionManager"。

由于有多个从PlatformTransactionManager继承的transactionManager,我们应该在每个@Transactional注释中指定要使用哪个transactionManager。

默认Repository配置

@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;
    }
}

另一个库的配置

@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());
    }
}

应用程序配置文件

# 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

选择适当的transactionManager作为@Transactional注释

第一个数据源的服务

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

   //

}

另一个数据源的服务

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

   //

}

抱歉,那是我的笔误。我需要重命名一些东西,但漏掉了那个。那不是问题,但还是谢谢你的努力。 - Mike3355
这个救了我!想补充一下,照字面意思执行时,在 1.5.2.RELEASE 上可以成功运行。 - Brian
我能够在任何实现类中不使用@Transactional注释的情况下,向两个不同的数据源进行交易。这种行为是否是预期的? 使用Spring-Boot 1.5.6.RELEASE - Purushothaman
我相信Spring通过AOP自动代理和@Transactional注解来管理事务。我发现Spring Data Rest中的@RepositoryRestResource等一些Spring技术能够自动地工作而无需@Transactional注解。我猜测在编译时会生成一定量的代码和层次结构,并默认设置事务。然而,我想知道如何为需要使用不同类型数据库的服务或存储库分配不同的transactionManager,而又不必进行特别说明。 - Steve Park

9

这是我的解决方案。基于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;
    }
}

6
如何引用这个?我已经做到了这一步,但我不知道如何通过JPA“召唤”第二个数据源。我想这可能需要在实体注释或查询参数中进行设置之类的操作。 - Alex Pineda
1
@Autowired @Qualifier("firstDataSource") private DataSource firstDataSource;@Autowired @Qualifier("secondDataSource") private DataSource secondDataSource; - david
1
你如何使用它创建或召唤第二个实体管理器?我正在努力做到这一点。 - GarouDan
1
有人成功让这个工作了吗?将自定义的数据源与JPA链接起来,还是人们只是在没有真实示例的情况下假设事情? - S34N
2
我注意到这个解决方案只有在两个数据库都映射到同一个JDBC驱动程序时才有效。然而,当您有两个连接到不同驱动程序的不同数据源时,它将无法工作。例如:一个驱动程序使用MariaDB驱动程序,另一个驱动程序使用IBM DB2Driver... - S34N

3
我查看了你在GitHub上提供的源代码。配置文件中存在几个错误/拼写错误。
在CustomerDbConfig/OrderDbConfig中,您应该引用customerEntityManager,并且packages应该指向现有的包:
@Configuration
@EnableJpaRepositories(
    entityManagerFactoryRef = "customerEntityManager",
    transactionManagerRef = "customerTransactionManager",
    basePackages = {"com.mm.boot.multidb.repository.customer"})
public class CustomerDbConfig {

在customerEntityManager和orderEntityManager中扫描的包都没有正确指向:

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

同时注入正确的EntityManagerFactory也没有起作用。应该是:

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

}

以上内容导致了该问题和异常。在@ Bean方法中提供名称时,您可以确保获得正确的EMF注入。
我最后做的事情是禁用JpaRepositories的自动配置:
@EnableAutoConfiguration(exclude = JpaRepositoriesAutoConfiguration.class)

经过所有修复,应用程序会按照您预期的方式启动!


首先,感谢您。我现在遇到了一个“org.springframework.beans.factory.NoUniqueBeanDefinitionException: No qualifying bean of type [javax.persistence.EntityManagerFactory] is defined: expected single matching bean but found 2: customerEntityManager,orderEntityManager”的异常。已经在GitHub上更新了建议的更改。 - tonym2105
1
EntityManagerInViewInterceptor自动配置导致了这个问题。你可以在应用程序属性中提供spring.jpa.open_in_view = false来轻松地禁用它。 - Rafal Borowiec
可以这样做。但是禁用该属性会有什么影响呢?再次感谢您的帮助。 - tonym2105
Spring Web请求拦截器,用于将JPA EntityManager绑定到线程以便在整个请求处理过程中使用。旨在实现“在视图中开放EntityManager”的模式,即使原始事务已经完成,也允许Web视图进行懒加载。 - Rafal Borowiec
这两个实体都在同一个数据库中创建。我在H2和MySQL中都注意到了这一点。非常感谢任何帮助。 - tonym2105
我该如何告诉/配置Spring,使得这个实体/存储库属于这个数据库? - IllSc

1
由于Steve Park和Rafal Borowiec的答案,我让我的代码工作了,但是我有一个问题:DriverManagerDataSource是一种“简单”的实现,并且不提供ConnectionPool(请检查http://docs.spring.io/spring/docs/current/javadoc-api/org/springframework/jdbc/datasource/DriverManagerDataSource.html)。因此,我替换了返回secondDBDataSource的函数。
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();
}

此外,如果您不需要 EntityManager,则可以删除 entityManager()@Bean 注释。另外,您可能想要删除配置类的 basePackages 注释:使用 factoryBean.setPackagesToScan() 调用来维护它就足够了。

1
我已经在Spring Boot JPA多数据源示例中编写了一篇完整的文章。在本文中,我们将学习如何在典型的Spring Boot Web应用程序中配置多个数据源并连接到多个数据库。我们将使用Spring Boot 2.0.5、JPA、Hibernate 5、Thymeleaf和H2数据库构建一个简单的Spring Boot多数据源Web应用程序。

-2

不知道为什么,但它可以工作。两个配置是相同的,只需将 xxx 更改为您的名称。

@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;
}

}


数据源.xxx.url = 数据源.xxx.username = 数据源.xxx.password = 数据源.xxx.driver-class-name = com.mysql.jdbc.Driver - dongwenting

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接