无法使用 Spring-Boot 创建多个数据源

     2023-02-26     220

关键词:

【中文标题】无法使用 Spring-Boot 创建多个数据源【英文标题】:Unable to create multiple datasources with Spring-Boot 【发布时间】:2017-04-17 12:22:51 【问题描述】:

tomcat 出现以下错误:

09:06:18,168 WARNING [org.apache.tomcat.jdbc.pool.PooledConnection] (ServerService Thread Pool -- 6) Not loading a JDBC driver as driverClassName property is null.
09:06:18,170 SEVERE [org.apache.tomcat.jdbc.pool.ConnectionPool] (ServerService Thread Pool -- 6) Unable to create initial connections of pool.: java.sql.SQLException: The url cannot be null

我在 JBOSS 和嵌入式 tomcat 服务器中都运行过这个,但仍然出现这个错误。我什至从war中取出jar文件并从JBOSS运行它,仍然得到同样的错误。

我能够创建 EntityMangers,但在创建它们之前我得到了上述错误。该程序继续运行而不是抱怨一个类不是托管类型。但是那些@Entities 正在被扫描。

我在使用 JBOSS 时遇到同样的错误:

09:06:18,171 WARN  [org.hibernate.engine.jdbc.env.internal.JdbcEnvironmentInitiator] (ServerService Thread Pool -- 6) HHH000342: Could not obtain connection to query metadata : The url cannot be null
09:06:18,183 INFO  [org.hibernate.dialect.Dialect] (ServerService Thread Pool -- 6) HHH000400: Using dialect: org.hibernate.dialect.Oracle10gDialect
09:06:18,199 INFO  [org.hibernate.engine.jdbc.env.internal.LobCreatorBuilderImpl] (ServerService Thread Pool -- 6) HHH000422: Disabling contextual LOB creation as connection was null

数据源:

@Configuration
@PropertySource("classpath:application.yml")
public class MainDataSourceConfig 
    
    /*******************************
     *       Datasource     *
     * *****************************/
    @Bean
    @Primary
    @ConfigurationProperties(prefix = "spring.dataSource.Main")
    public DataSource mainDataSource() 
        return DataSourceBuilder.create().build();
    
    
    /*******************************
     *  Transaction manager *
     * *****************************/
    @Bean
    @Primary
    DataSourceTransactionManager transactionManager(@Qualifier("mainDataSource") DataSource datasource) 
        DataSourceTransactionManager txm = new DataSourceTransactionManager(datasource);
        return txm;
    
    
    @Bean
    @Primary
    public LocalContainerEntityManagerFactoryBean entityManagerFactory(@Qualifier("mainDataSource")DataSource dataSource) 
        LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
        entityManagerFactory.setPersistenceUnitName("mainEntityManger");
        entityManagerFactory.setDataSource(dataSource);
        entityManagerFactory.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
        entityManagerFactory.setJpaDialect(new HibernateJpaDialect());
        entityManagerFactory.setPackagesToScan("com.customers.domain");
        
        entityManagerFactory.setJpaProperties(additionalProperties());
        return entityManagerFactory;
    
    
    private Properties additionalProperties() 
        Properties properties = new Properties();
        properties.setProperty("hibernate.dialect", "org.hibernate.dialect.Oracle10gDialect");
        properties.setProperty("hibernate.ddl-auto","none");
        return properties;
    
    

第二个数据源

@Configuration
@PropertySource("classpath:application.yml")
public class SecondDataSourceConfig 
    
    /*******************************
     *      Datasource      *
     * *****************************/
    @Bean
    @ConfigurationProperties(prefix="spring.dataSource.Second")
    public DataSource secondDataSource() 
        return DataSourceBuilder.create().build();
    
    
    /*******************************
     *  Transaction manager *
     * *****************************/
    @Bean
    DataSourceTransactionManager transactionManager(@Qualifier("secondDataSource") DataSource datasource) 
        DataSourceTransactionManager txm  = new DataSourceTransactionManager(datasource);
        return txm;
    
    
    @Bean
    public LocalContainerEntityManagerFactoryBean keyviewEntityMangerFactory(@Qualifier("secondDataSource") DataSource dataSource) 
        LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
        entityManagerFactory.setPersistenceUnitName("secondEntityManger");
        entityManagerFactory.setDataSource(dataSource);
        entityManagerFactory.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
        entityManagerFactory.setJpaDialect(new HibernateJpaDialect());
        entityManagerFactory.setPackagesToScan("com.statements.domain");
        entityManagerFactory.setJpaProperties(additionalProperties());
        
        return entityManagerFactory;
    
    
    private Properties additionalProperties() 
        Properties properties = new Properties();
        properties.setProperty("hibernate.dialect", "org.hibernate.dialect.Oracle10gDialect");
        properties.setProperty("hibernate.ddl-auto","none");
        
        return properties;
    
            

application.yml

#Spring Boot Config for Oracle
spring:
  dataSource:
    Main:
      url: [url]
      username: [username]
      password: [password]
      driverClassName: oracle.jdbc.OracleDriver

    Second:
      url: [url]
      username: [username]
      password: [password]
      driverClassName: oracle.jdbc.OracleDriver

    tomcat:
      min-idle: 1

# Spring Boot Actuator settings
#https://docs.spring.io/spring-boot/docs/current/reference/html/production-ready-endpoints.html
endpoints.health.sensitive: false
#management.security.enabled: true
management.context-path: /healthCheck

endpoints.info.id: info
endpoints.info.sensitive: false
endpoints.info.enabled: true
info.app.name: Request
info.app.description: Request Description
info.app.version: 0.0.1-SNAPSHO

我已经做了一个多星期了,我无法弄清楚为什么它说 url 为空,后来创建 entityManagers 时说我的一个域包不是托管类型。扫描第二组软件包似乎有问题。我确认了更改类名,因为我注意到它是按字母顺序编译的,当我这样做时,它改变了它抱怨的包。 #note:每次我运行同一个包时,它都会选择一个不同的类,并且它们是 @Entity 注释的。

我也在 main 方法上使用@EntityScan@ComponentScan@SpringBootApplication@EnableAutoConfiguration

注意:当我删除第二个数据源时,一切正常。只有当我引入第二个时才会发生这种情况。

------------更新1--------- --------------

我只是将数据源信息放入两个不同的yml 文件中,但仍然出现相同的错误。然后我决定把主要的数据源拿出来,把第二个作为项目中唯一的一个来实现。 那么我得到了同样的错误。但是 URI 和一切都是正确的,不知道为什么会这样。

【问题讨论】:

【参考方案1】:

我最近在使用 spring boot(没有 SpringBootApplication 注释)创建测试工具时遇到了类似的问题,我最终发现我需要使用数据源属性并在配置类中显式指定 @EnableConfigurationProperties:

@Configuration
@EnableConfigurationProperties(value = DataSourceProperties.class)
public class ....

为数据源属性定义的bean:

@Bean(name = "ds1Props")
@ConfigurationProperties(prefix = "path.to.ds1.properties")
public DataSourceProperties ds1DataSourceProperties() 
    return new DataSourceProperties();


@Bean(name = "ds2Props")
@ConfigurationProperties(prefix = "path.to.ds2.properties")
public DataSourceProperties ds2DataSourceProperties() 
    return new DataSourceProperties();

然后将它们注入到数据源bean方法中:

@Bean
public DataSource dataSource1(@Qualifier("ds1Props") DataSourceProperties ds1Props) 
    return ds1Props.initializeDataSourceBuilder().build();


@Bean
public DataSource dataSource2(@Qualifier("ds2Props") DataSourceProperties ds2Props) 
    return ds2Props.initializeDataSourceBuilder().build();

希望这对您有所帮助或助您一臂之力。我不确定为什么需要将其显式设置为 jdbc 自动配置的一部分。 (我想可能是因为我的数据源配置后可能会处理spring boot数据源配置)

--- 更新:基于原始源的工作示例,修改以匹配我的数据库环境,使用带有 starter web 和 starter jpa 包的 spring boot 1.3.1。 @Primary 需要满足对自动配置的 DataSourceInitializer 和 OpenSessionInViewInterceptor 的依赖关系。

@SpringBootApplication
public class Application 

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


@Primary
@Bean
@ConfigurationProperties(prefix = "spring.dataSource.Main")
public DataSource mainDataSource() 
    return DataSourceBuilder.create().build();


@Bean
DataSourceTransactionManager mainTransactionManager(@Qualifier("mainDataSource") DataSource datasource) 
    DataSourceTransactionManager txm = new DataSourceTransactionManager(datasource);
    return txm;


@Primary
@Bean
public LocalContainerEntityManagerFactoryBean mainEntityManagerFactory(
        @Qualifier("mainDataSource") DataSource dataSource) 
    LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
    entityManagerFactory.setPersistenceUnitName("mainEntityManger");
    entityManagerFactory.setDataSource(dataSource);
    entityManagerFactory.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
    entityManagerFactory.setJpaDialect(new HibernateJpaDialect());
    entityManagerFactory.setPackagesToScan("com.sbp.domain.main");
    entityManagerFactory.setJpaProperties(additionalProperties());
    return entityManagerFactory;


@Bean
@ConfigurationProperties(prefix = "spring.dataSource.Second")
public DataSource secondDataSource() 
    return DataSourceBuilder.create().build();


@Bean
DataSourceTransactionManager secondTransactionManager(@Qualifier("secondDataSource") DataSource datasource) 
    DataSourceTransactionManager txm = new DataSourceTransactionManager(datasource);
    return txm;


@Bean
public LocalContainerEntityManagerFactoryBean secondEntityMangerFactory(
        @Qualifier("secondDataSource") DataSource dataSource) 
    LocalContainerEntityManagerFactoryBean entityManagerFactory = new LocalContainerEntityManagerFactoryBean();
    entityManagerFactory.setPersistenceUnitName("secondEntityManger");
    entityManagerFactory.setDataSource(dataSource);
    entityManagerFactory.setJpaVendorAdapter(new HibernateJpaVendorAdapter());
    entityManagerFactory.setJpaDialect(new HibernateJpaDialect());
    entityManagerFactory.setPackagesToScan("com.sbp.domain.second");
    entityManagerFactory.setJpaProperties(additionalProperties());
    return entityManagerFactory;


private Properties additionalProperties() 
    Properties properties = new Properties();
    properties.setProperty("hibernate.dialect", "org.hibernate.dialect.MySQL5Dialect");
    properties.setProperty("hibernate.ddl-auto", "none");
    return properties;


【讨论】:

我按照你说的做了,事情看起来很积极,但现在它说应用程序无法启动。描述:Cannot determine embedded database driver class for database type NONE 操作:If you want an embedded database please put a supported one on the classpath. If you have database settings to be loaded from a particular profile you may need to active it (no profiles are currently active). 但它只针对第二个数据源说。 Unsatisfied dependency expressed through method 'secondEntityMangerFactory' parameter 0; nested exception is org.springframework.beans.factory.BeanCreationException: 能分享一下spring boot版本和你拉进来的boot包吗?我在上面获取了您的原始代码,使用已启动的 web 和 starter jpa 创建了一个项目,并且能够毫无错误地启动应用程序。 also - 这是另一个具有替代实现但细节很好的帖子。 ***.com/questions/26308035/… 这里是我使用您的原始源代码创建的应用程序的完整源代码:【参考方案2】:

您需要设置两组具有唯一名称的 bean(即 transactionManager2)

摆脱@Primary - 说把这个bean放在另一个上面。在这种情况下,您需要上下文中的两个 bean - 因此需要唯一的名称。

见:http://docs.spring.io/spring-boot/docs/current/reference/html/howto-data-access.html

如果您使用的是 Spring Data JPA,请执行以下操作:

@Configuration
@EnableJpaRepositories(basePackageClasses = Customer.class,
        entityManagerFactoryRef = "customerEntityManagerFactory")
public class CustomerConfiguration 
    ...


@Configuration
@EnableJpaRepositories(basePackageClasses = Order.class,
        entityManagerFactoryRef = "orderEntityManagerFactory")
public class OrderConfiguration 
    ...

【讨论】:

在春季批处理(spring-boot-1.5.2.RELEASE)中使用多个数据源在启动时引发异常

】在春季批处理(spring-boot-1.5.2.RELEASE)中使用多个数据源在启动时引发异常【英文标题】:Usingmultipledatasourcesinspringbatch(spring-boot-1.5.2.RELEASE)throwingexceptiononbootup【发布时间】:2017-12-2900:01:33【问题描述】:我正在尝试使用两个数... 查看详情

使用 Google Cloud Pub/Sub 消息订阅者实现时无法创建 Spring-Boot bean

】使用GoogleCloudPub/Sub消息订阅者实现时无法创建Spring-Bootbean【英文标题】:Spring-BootbeanfailedtocreatewhenusingGoogleCloudPub/Submessagesubscriberimplementation【发布时间】:2019-11-1013:25:43【问题描述】:我正在尝试运行一个具有Spring-Boot、具有... 查看详情

在 spring-boot 中使用一个模板引擎渲染多个后缀

】在spring-boot中使用一个模板引擎渲染多个后缀【英文标题】:rendermultiplesuffixeswithonetemplateengineinspring-boot【发布时间】:2017-09-3017:53:28【问题描述】:我创建了两个thymleaf解析器并将它们添加到模板引擎中,因此我可以在spring-bo... 查看详情

如何通过使用 JPA + Hibernate 和 Spring-boot 在一个数据库中使用多个模式?

】如何通过使用JPA+Hibernate和Spring-boot在一个数据库中使用多个模式?【英文标题】:Howtousemultipleschema\'sinonedatabasebyusingJPA+HibernatewithSpring-boot?【发布时间】:2018-11-1812:48:44【问题描述】:我需要它在一个数据库(MySQL)中访问2个... 查看详情

无法实现对 Spring-Boot API 的基于角色的访问

】无法实现对Spring-BootAPI的基于角色的访问【英文标题】:UnabletoimplementRolebasedaccesstoSpring-BootAPI【发布时间】:2019-12-1100:18:34【问题描述】:我是Spring-Boot的新手。我想创建一个API,该API将具有基于角色的访问权限和基于JWT令牌... 查看详情

spring-boot 应用程序不会将夹具加载到多个数据源之一

】spring-boot应用程序不会将夹具加载到多个数据源之一【英文标题】:spring-bootapplicationdoesn\'tloadfixturesintooneofmultipledatasources【发布时间】:2017-08-2411:16:44【问题描述】:在我的SpringBoot应用程序(1.5.2.RELEASE)启动期间加载数据固定... 查看详情

无法在 spring-boot 应用程序中从 Consul 读取配置

】无法在spring-boot应用程序中从Consul读取配置【英文标题】:NotabletoreadconfigurationfromConsulinspring-bootapplication【发布时间】:2018-05-1323:05:32【问题描述】:我正在创建一个SpringBoot应用程序,它将从Consul读取数据库属性等配置。但我... 查看详情

Camel:使用 spring-boot 配置的数据源

】Camel:使用spring-boot配置的数据源【英文标题】:Camel:usedatasourceconfiguredbyspring-boot【发布时间】:2015-10-1312:18:11【问题描述】:我有一个项目,我在其中使用spring-boot-jdbc-starter,它会自动为我配置一个数据源。现在我将camel-sprin... 查看详情

使用 Apache Derby 作为嵌入式数据库的 Spring-boot 错误

】使用ApacheDerby作为嵌入式数据库的Spring-boot错误【英文标题】:Spring-booterrorusingApacheDerbyasembeddeddatabase【发布时间】:2017-08-3119:56:04【问题描述】:我是使用弹簧靴的新手。我正在尝试使用apachederby作为嵌入式数据库创建RESTAPI,... 查看详情

无法创建多个 ID,但我只有一个

】无法创建多个ID,但我只有一个【英文标题】:CannotcreateMultipleIdsbutyetIonlyhaveone【发布时间】:2018-10-0621:59:15【问题描述】:如您所见,我正在使用一个主键创建一个新类,我删除了数据库以重新创建它,但是publicclassCustomerCont... 查看详情

无法使用 MongoDB + Node 创建多个对象

】无法使用MongoDB+Node创建多个对象【英文标题】:Can\'tcreatemultipleobjectswithMongoDB+Node【发布时间】:2021-11-0915:44:06【问题描述】:我正在尝试使用mongodb、mongoose和express(通过使用Insomnia)创建多个对象。我设法创建了第一个对象... 查看详情

如何使用spring-boot处理越来越多的stomp主题

我目前正在开发一个Spring-boot应用程序,它通过Web套接字使用STOMP与前端进行通信。在我的解决方案中,我计划,客户端定期订阅新的动态生成的主题(例如:/app/topic/some/object/{id}),这些主题使用了一段时间然后被遗忘,其他... 查看详情

Spring-Boot:同时处理多个请求

】Spring-Boot:同时处理多个请求【英文标题】:Spring-Boot:Handlemultiplerequestsconcurrently【发布时间】:2018-02-2316:32:39【问题描述】:我正在使用SpringBoottobuildaRESTfulwebservice。我的IDE是EclipseOxygen。我通过Chrome每2秒发送多个HTTPget请求,... 查看详情

无法使用 Django REST 框架从多个选择元素中发布 JSON 数据

】无法使用DjangoREST框架从多个选择元素中发布JSON数据【英文标题】:UnabletoPOSTJSONdatafrommultipleselectelementwithDjangoRESTFramework【发布时间】:2019-12-2918:47:54【问题描述】:我希望能够向我的API端点发送AJAXPOST请求,以创建我的Asset模... 查看详情

无法在 android studio SQLite 数据库中动态创建多个表

】无法在androidstudioSQLite数据库中动态创建多个表【英文标题】:Can\'tcreatemorethanonetabledynamicallyinandroidstudioSQLitedatabase【发布时间】:2021-09-1922:01:41【问题描述】:我正在尝试在androidstudioSQLite数据库中动态创建多个表。我在下面... 查看详情

无法使用#pragma omp parallel for 创建多个线程

】无法使用#pragmaompparallelfor创建多个线程【英文标题】:failedtocreatemorethanonethreadwith#pragmaompparallelfor【发布时间】:2013-03-1410:57:23【问题描述】:所有。我是OpenMP的初学者。我想像这样使用OpenMP:float*Arrays;intOneArrayLength=100;float*Ar... 查看详情

如何使用带有 gradle 的多个嵌入式服务器运行 spring-boot 集成测试

】如何使用带有gradle的多个嵌入式服务器运行spring-boot集成测试【英文标题】:howtorunspring-bootintegrationtestswithmultipleembededserverswithgradle【发布时间】:2016-11-0315:43:27【问题描述】:我对我的SpringBoot应用程序进行了一些集成测试。... 查看详情

无法使用多个 IIS 应用程序创建弹性 beanstalk

】无法使用多个IIS应用程序创建弹性beanstalk【英文标题】:CannotcreateelasticbeanstalkwithmultipleIISapplications【发布时间】:2014-02-1000:27:29【问题描述】:我正在尝试将生产Web服务器迁移到AWS,该服务器是基于Windows的IIS,在1个网站下定... 查看详情