当前位置: 首页 > 知识库问答 >
问题:

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

梁骞仕
2023-03-14

我在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,但在创建它们之前,我得到了上面的错误。程序继续运行比抱怨类不是托管类型。但是,这些@实体正在被扫描。

我在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创建时,它会说我的一个域包不是托管类型。它似乎有一个问题扫描第二组包。我确认了这一点,更改了类名,因为我注意到它是按字母顺序编译的,当我这样做时,它改变了它抱怨的包。#注意:每次我运行相同包的类时,它都会选择不同的类,并且这些类被注释为@entity

我还在main方法上使用@EntityScan@ComponentScan@SpringBootApplication@enableAutoConfiguration

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

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

共有1个答案

蓬弘
2023-03-14

我最近在使用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 datasource配置可能是在我的数据源配置之后处理的)

---更新:基于原始源代码的工作示例,经过修改以匹配我的db环境,使用spring boot 1.3.1和starter web和starter jpa包。@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;
}
}
 类似资料:
  • 我正在尝试使用JPA生成表。但我不能创造它。代码中没有错误,但似乎存在配置错误。但我找不到它,我尝试了很多配置但没有发生。多谢. 这是: } pom.xml

  • 问题内容: 我正在使用Spring Boot。我终于设法设置了两个数据源,但是现在我面临另一个问题。 有两个数据源的地方似乎无法在我的Spring Boot应用程序中工作,请立即执行此操作 我无法为每个数据源选择自动创建策略。我宁愿为数据源一创建模式,而仅在第二个DB中使用数据源为二的模式。 任何机构都知道如何解决这些问题?注意如果可能的话,我不想完全放弃自动配置。我什至还不知道,hibernat

  • 我试图创建一个Spring Boot应用程序,它连接两个数据源。我可以通过遵循Spring文档来实现这一点,但我面临的挑战是实现以下目标 null 是否有任何方法可以使用Spring Boot的自动配置功能来实现这一点,或者我必须基于概要文件创建不同的数据源bean。

  • 问题内容: 我对Spring Boot还是很陌生,我想为我的项目创建一个多数据源。这是我目前的情况。我有两个用于多个数据库的实体包。比方说 所以,目前我有两个实体类 UserMySql.java 我想实现一个配置,如果我从UserMySql创建用户,它将被保存到MySql数据库,如果我从Userh2创建用户,它将被保存到H2数据库。所以,我也有两个DBConfig,比如说MySqlDbConfig

  • 我有一个使用1.5.1版本spring boot的应用程序的问题。 启动程序时出现以下错误: 我尝试使用@primary,但当我需要使用其他数据源时,它不起作用。 谢谢你

  • 我想用mysql服务器中的这些信息创建一个名为dni的表。 失败的查询: 1.“创建表dni(id bigint not null,apellidos varchar(255),codigo_dni varchar(255),direccion varchar(255),fecha_nacimiento varchar(255),foto_perfil varchar(255),nombre va