SpringBoot项目配置多数据源(使用SpringDataJpa前提下添加JdbcTemplate连接vertica)

背景

由于“续转卡文件下发平台对接迁移”的需求,营销风险管理平台系统(SpringBoot项目)将续转卡文件的上传方式由原来的调用pass-steaming作业从sqlSever直接传输到ftp,改为先在Vertica建立临时表,再调用Ucp作业将Vertica的临时表转移至目的ftp。

设计

在不影响项目原有使用SpringDataJpa操作sqlServer逻辑的基础上,添加jdbcTemplate操作Vertica数据库

过程及问题

原有sqlServer DataSource的相关配置在application.properties文件中,在applicationContext.xml中添加vertica DataSource及vertica jdbcTemplate的配置,项目启动报错:

2022-01-25 09:18:20.021  INFO 27420 --- [           main] c.m.v.c.i.AbstractPoolBackedDataSource   : Initializing c3p0 pool... com.mchange.v2.c3p0.ComboPooledDataSource [ acquireIncrement -> 3, acquireRetryAttempts -> 30, acquireRetryDelay -> 1000, autoCommitOnClose -> false, automaticTestTable -> null, breakAfterAcquireFailure -> false, checkoutTimeout -> 0, connectionCustomizerClassName -> null, connectionTesterClassName -> com.mchange.v2.c3p0.impl.DefaultConnectionTester, contextClassLoaderSource -> caller, dataSourceName -> rir9c9am13micw31u0wl9k|5f06a4ec, debugUnreturnedConnectionStackTraces -> false, description -> null, driverClass -> null, extensions -> {}, factoryClassLocation -> null, forceIgnoreUnresolvedTransactions -> false, forceSynchronousCheckins -> false, forceUseNamedDriverClass -> false, identityToken -> rir9c9am13micw31u0wl9k|5f06a4ec, idleConnectionTestPeriod -> 100, initialPoolSize -> 1, jdbcUrl -> jdbc:vertica://99.47.151.179:5433/cmb01, maxAdministrativeTaskTime -> 0, maxConnectionAge -> 0, maxIdleTime -> 1800, maxIdleTimeExcessConnections -> 0, maxPoolSize -> 2, maxStatements -> 0, maxStatementsPerConnection -> 0, minPoolSize -> 1, numHelperThreads -> 3, preferredTestQuery -> select 1, privilegeSpawnedThreads -> false, properties -> {user=******, password=******}, propertyCycle -> 0, statementCacheNumDeferredCloseThreads -> 0, testConnectionOnCheckin -> true, testConnectionOnCheckout -> true, unreturnedConnectionTimeout -> 0, userOverrides -> {}, usesTraditionalReflectiveProxies -> false ]
2022-01-25 09:18:21.811  INFO 27420 --- [           main] j.LocalContainerEntityManagerFactoryBean : Building JPA container EntityManagerFactory for persistence unit 'default'
2022-01-25 09:18:21.844  INFO 27420 --- [           main] o.hibernate.jpa.internal.util.LogHelper  : HHH000204: Processing PersistenceUnitInfo [
    name: default
    ...]
2022-01-25 09:18:22.012  INFO 27420 --- [           main] org.hibernate.Version                    : HHH000412: Hibernate Core {5.2.17.Final}
2022-01-25 09:18:22.016  INFO 27420 --- [           main] org.hibernate.cfg.Environment            : HHH000206: hibernate.properties not found
2022-01-25 09:18:22.119  INFO 27420 --- [           main] o.hibernate.annotations.common.Version   : HCANN000001: Hibernate Commons Annotations {5.0.1.Final}
2022-01-25 09:18:23.580  WARN 27420 --- [           main] o.h.e.j.e.i.JdbcEnvironmentInitiator     : HHH000342: Could not obtain connection to query metadata : Unable to determine Dialect to use [name=Vertica Database, majorVersion=9]; user must register resolver or explicitly set 'hibernate.dialect'
2022-01-25 09:18:23.584  WARN 27420 --- [           main] ConfigServletWebServerApplicationContext : Exception encountered during context initialization - cancelling refresh attempt: org.springframework.beans.factory.BeanCreationException: Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]: Invocation of init method failed; nested exception is org.hibernate.service.spi.ServiceException: Unable to create requested service [org.hibernate.engine.jdbc.env.spi.JdbcEnvironment]
2022-01-25 09:18:23.586  WARN 27420 --- [           main] o.s.b.f.support.DisposableBeanAdapter    : Destroy method 'close' on bean with name 'eurekaRegistration' threw an exception: org.springframework.beans.factory.BeanCreationNotAllowedException: Error creating bean with name 'org.springframework.cloud.netflix.eureka.EurekaClientAutoConfiguration$RefreshableEurekaClientConfiguration': Singleton bean creation not allowed while singletons of this factory are in destruction (Do not request a bean from a BeanFactory in a destroy method implementation!)
2022-01-25 09:18:23.608  INFO 27420 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService
2022-01-25 09:18:23.623  INFO 27420 --- [           main] o.s.s.concurrent.ThreadPoolTaskExecutor  : Shutting down ExecutorService 'hunterAsyncExecutor'
2022-01-25 09:18:23.624  INFO 27420 --- [           main] o.apache.catalina.core.StandardService   : Stopping service [Tomcat]
......
org.springframework.beans.factory.BeanCreationException:
Error creating bean with name 'entityManagerFactory' defined in class path resource.
......
Caused by:
org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set

控制台提示hibernate的dialect没有设置,可是这里jdbcTemplate和vertica datasource的配置和hibernate应该是不存在关联的,因此开始排查问题。

排查

从报错日志:

Error creating bean with name 'entityManagerFactory' defined in class path resource [org/springframework/boot/autoconfigure/orm/jpa/HibernateJpaConfiguration.class]

中定位到HibernateJpaConfiguration这个类,
在这里插入图片描述
可以看到该类使用了@ConditionalOnSingleCandidate(DataSource.class) 注解,进一步查看这个注解:
在这里插入图片描述
从注解的解释中可以看出,当BeanFactory中已经存在了多个符合条件的Bean时,会指定匹配primary Bean。这里的Bean对应的就是DataSource。

在未添加Vertica DataSource的时候,项目正常启动,应用上下文中有且只有一个sqlServer DataSource被HibernateJpaConfiguration识别加载;添加Vertica DataSource之后,applicationContext.xml中配置的Vertica DataSource首先被HibernateJpaConfiguration加载,由于Hibernate已配置的方言列表中未包含Vertica,因此报错:

org.hibernate.HibernateException: Access to DialectResolutionInfo cannot be null when 'hibernate.dialect' not set。

解决方法

既然问题是由于Vertica DataSource首先被HibernateJpaConfiguration加载导致的,那么只需要和原来保持一致,使sqlServer DataSource优先被加载即可解决问题。因此将applicationContext.xml中的vertica DataSource和vertica JdbcTemplate改为代码的方式配置,同样以代码的方式配置sqlServer DataSource,并添加@Primary注解,使其被优先加载。

@Configuration
public class VerticaJdbcTemplateConfig {
    @Primary
    @Bean(name = "DataSource")
    @ConfigurationProperties(prefix = "spring.datasource")
    public HikariDataSource primaryDataSource() {
        return DataSourceBuilder.create().type(HikariDataSource.class).build();
    }
 
 
    @Bean(name = "verticaDataSource")
    @ConfigurationProperties(prefix = "vertica.datasource")
    ComboPooledDataSource verticaDataSource() {
        return DataSourceBuilder.create()
                .type(ComboPooledDataSource.class).build();
    }
 
    @Bean(name = "verticaJdbcTemplate")
    JdbcTemplate verticaJdbcTemplate(@Qualifier("verticaDataSource") ComboPooledDataSource comboPooledDataSource) {
        return new JdbcTemplate(comboPooledDataSource);
    }
}

在application.properties中配置DataSource具体参数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
在Spring Boot项目配置数据,可以使用Spring Boot提供的多数据支持。以下是一个简单的示例: 首先在application.properties中配置数据的相关信息: ``` # 数据1 spring.datasource.url=jdbc:mysql://localhost/test1 spring.datasource.username=root spring.datasource.password=password1 spring.datasource.driver-class-name=com.mysql.jdbc.Driver # 数据2 spring.datasource.secondary.url=jdbc:mysql://localhost/test2 spring.datasource.secondary.username=root spring.datasource.secondary.password=password2 spring.datasource.secondary.driver-class-name=com.mysql.jdbc.Driver ``` 然后定义两个数据配置类: ```java @Configuration @Primary @ConfigurationProperties("spring.datasource") public class DataSource1Config extends HikariDataSource { } @Configuration @ConfigurationProperties("spring.datasource.secondary") public class DataSource2Config extends HikariDataSource { } ``` 在这个示例中,我们使用了HikariCP作为连接池,分别定义了两个数据配置类。其中,@Primary注解表示默认使用第一个数据。 接下来,定义两个JdbcTemplate的实例: ```java @Bean(name = "jdbcTemplate1") public JdbcTemplate jdbcTemplate1(@Qualifier("dataSource1") DataSource dataSource) { return new JdbcTemplate(dataSource); } @Bean(name = "jdbcTemplate2") public JdbcTemplate jdbcTemplate2(@Qualifier("dataSource2") DataSource dataSource) { return new JdbcTemplate(dataSource); } ``` 在这个示例中,我们使用了@Qualifier注解来指定要使用数据。 最后,在需要访问不同数据的地方注入相应的JdbcTemplate即可,例如: ```java @Autowired @Qualifier("jdbcTemplate1") private JdbcTemplate jdbcTemplate1; @Autowired @Qualifier("jdbcTemplate2") private JdbcTemplate jdbcTemplate2; ``` 在实际使用中,我们可以根据需要自由切换数据,以访问不同的数据库。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值