Spring data jdbc - 多个数据源 - 不从二级

问题描述

用例:从oracle读取数据并加载到MysqL中。

我们使用的是 Spring Data JDBC 和 OJDBC8。

问题:始终连接到主数据源。

**application.properties**
=======================

spring.datasource.MysqL.jdbcUrl = jdbc:MysqL://localhost:3306/MysqLData?useSSL=false
spring.datasource.MysqL.username = root
spring.datasource.MysqL.password = root
spring.datasource.MysqL.driverClassName = com.MysqL.cj.jdbc.Driver


spring.datasource.oracle.jdbcUrl = jdbc:oracle:thin:@localhost:1521/XE
spring.datasource.oracle.username = root
spring.datasource.oracle.password = ea
spring.datasource.oracle.driverClassName = oracle.jdbc.OracleDriver

**MysqLDataSource.java**
=====================

package com.test.datasource;

@Configuration
@EnableJdbcRepositories(transactionManagerRef = "mysqljdbcTransactionManager",jdbcoperationsRef = "mysqljdbcOperationsReference",basePackages = {
        "com.test.data.MysqL.repository" })
@EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class,JdbcRepositoriesAutoConfiguration.class })
public class MysqLDataSource extends AbstractJdbcConfiguration {

    @Bean
    @Primary
    @Qualifier("MysqLDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.MysqL")
    public DataSource dataSourceMysqL() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    @Primary
    @Qualifier("mysqljdbcOperationsReference")
    public NamedParameterJdbcoperations mysqljdbcOperationsReference(
            @Qualifier("MysqLDataSource") DataSource dataSource) {
        return new NamedParameterJdbcTemplate(dataSource);
    }

    @Bean
    @Primary
    @Qualifier("mysqljdbcTransactionManager")
    public PlatformTransactionManager mysqljdbcTransactionManager(@Qualifier("MysqLDataSource") final DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
}
**OracleDataSource.java**
======================

package com.test.datasource;

@Configuration
@EnableTransactionManagement
@EnableJdbcRepositories(transactionManagerRef = "oracleJdbcTransactionManager",jdbcoperationsRef = "oracleJdbcoperationsReference",basePackages = {
        "com.test.data.oracle.repository" })
@EnableAutoConfiguration(exclude = { DataSourceAutoConfiguration.class,JdbcRepositoriesAutoConfiguration.class })
public class OracleDataSource extends AbstractJdbcConfiguration {

    @Bean
    @Qualifier("oracleDataSource")
    @ConfigurationProperties(prefix = "spring.datasource.oracle")
    public DataSource dataSourceOracle() {
        return DataSourceBuilder.create().build();
    }

    @Bean
    @Qualifier("oracleJdbcoperationsReference")
    public NamedParameterJdbcoperations oracleJdbcoperationsReference(
            @Qualifier("oracleDataSource") DataSource dataSource) {
        return new NamedParameterJdbcTemplate(dataSource);
    }

    @Bean
    @Qualifier("oracleJdbcTransactionManager")
    public PlatformTransactionManager oracleJdbcTransactionManager(
            @Qualifier("oracleDataSource") final DataSource dataSource) {
        return new DataSourceTransactionManager(dataSource);
    }
}


package com.test.data.oracle.repository;

@Repository
public interface ServiceRepository extends CrudRepository<Service,Integer> {

}
**Controller.java**
====================
package com.test.controller;

@RestController
@RequestMapping(value = "/api/v1/bnService")
@Api(tags = { "Business Unit operations" })

public class BNServiceController {

    @Autowired
    private ServiceRepository  attributeGroupRepository;

    @RequestMapping(method = RequestMethod.GET,produces = MediaType.APPLICATION_JSON_VALUE)
    public SuccessVO retrieveConnectorInfoByCode() {

        Optional<Service>  pagedOtAttributeGroup = attributeGroupRepository.findById(52);
        return null;
    }   

}

**Logs**
========

Adding transactional method 'org.springframework.data.jdbc.repository.support.SimpleJdbcRepository.findById' with attribute: PROPAGATION_required,ISOLATION_DEFAULT,readOnly
Returning cached instance of singleton bean 'oracleJdbcTransactionManager'
Creating new transaction with name [org.springframework.data.jdbc.repository.support.SimpleJdbcRepository.findById]: PROPAGATION_required,readOnly
HikariPool-2 - configuration:
allowPoolSuspension.............false
autoCommit......................true
catalog.........................none
connectionInitsql...............none
connectionTestQuery.............none
connectionTimeout...............30000
dataSource......................none
dataSourceClassName.............none
dataSourceJNDI..................none
dataSourceProperties............{password=<masked>}
driverClassName................."oracle.jdbc.OracleDriver"
exceptionOverrideClassName......none
healthCheckProperties...........{}
healthCheckRegistry.............none
idleTimeout.....................600000
initializationFailTimeout.......1
isolateInternalQueries..........false
jdbcUrl.........................jdbc:oracle:thin:@localhost:1521/XE
leakDetectionThreshold..........0
maxLifetime.....................1800000
maximumPoolSize.................10
metricRegistry..................none
metricsTrackerFactory...........none
minimumIdle.....................10
password........................<masked>
poolName........................"HikariPool-2"
readOnly........................false
registerMbeans..................false
scheduledExecutor...............none
schema..........................none
threadFactory...................internal
transactionIsolation............default
username........................"ea"
validationTimeout...............5000
HikariPool-2 - Starting...
HikariPool-2 - Added connection oracle.jdbc.driver.T4CConnection@1bfa059c
HikariPool-2 - Start completed.
Acquired Connection [HikariProxyConnection@2136532594 wrapping oracle.jdbc.driver.T4CConnection@1bfa059c] for JDBC transaction
Setting JDBC Connection [HikariProxyConnection@2136532594 wrapping oracle.jdbc.driver.T4CConnection@1bfa059c] read-only
Switching JDBC Connection [HikariProxyConnection@2136532594 wrapping oracle.jdbc.driver.T4CConnection@1bfa059c] to manual commit
Bound value [org.springframework.jdbc.datasource.ConnectionHolder@55db8827] for key [HikariDataSource (HikariPool-2)] to thread [http-nio-8081-exec-2]
Initializing transaction synchronization
Getting transaction for [org.springframework.data.jdbc.repository.support.SimpleJdbcRepository.findById]
Executing prepared sql query
Fetching JDBC Connection from DataSource
Bound value [org.springframework.jdbc.datasource.ConnectionHolder@400a4f] for key [HikariDataSource (HikariPool-1)] to thread [http-nio-8081-exec-2]
Setting sql statement parameter value: column index 1,parameter value [52],value class [java.lang.Integer],sql type 4
Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@400a4f] for key [HikariDataSource (HikariPool-1)] bound to thread [http-nio-8081-exec-2]
Retrieved value [org.springframework.jdbc.datasource.ConnectionHolder@400a4f] for key [HikariDataSource (HikariPool-1)] bound to thread [http-nio-8081-exec-2]
Loading XML bean deFinitions from class path resource [org/springframework/jdbc/support/sql-error-codes.xml]
HikariPool-2 - Pool stats (total=1,active=1,idle=0,waiting=0)
Using JAXP provider [com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl]
Trying to resolve XML entity with public ID [-//SPRING//DTD BEAN 2.0//EN] and system ID [https://www.springframework.org/dtd/spring-beans-2.0.dtd]
Trying to locate [spring-beans.dtd] in Spring jar on classpath
Found beans DTD [https://www.springframework.org/dtd/spring-beans-2.0.dtd] in classpath: spring-beans.dtd
Alias deFinition 'Db2' registered for name 'DB2'
Alias deFinition 'Hana' registered for name 'HDB'
Alias deFinition 'Hsql' registered for name 'Hsql'
Alias deFinition 'sqlServer' registered for name 'MS-sql'
Alias deFinition 'Postgres' registered for name 'Postgresql'
Loaded 11 bean deFinitions from class path resource [org/springframework/jdbc/support/sql-error-codes.xml]

Caching sql error codes for DataSource [com.zaxxer.hikari.HikariDataSource@3b332962]: database product name is 'MysqL'
Translating sqlException with sql state '42S02',error code '1146',message [Table 'MysqLData.service' doesn't exist]; sql was [SELECT `service`.`SERVICE_ID` AS `SERVICE_ID`,`service`.`SERVICE_NAME` AS `SERVICE_NAME` FROM `service` WHERE `service`.`SERVICE_ID` = ?] for task [PreparedStatementCallback]

Completing transaction for **[org.springframework.data.jdbc.repository.support.SimpleJdbcRepository.findById] after exception: org.springframework.jdbc.BadsqlGrammarException: PreparedStatementCallback; bad sql grammar [SELECT `service`.`SERVICE_ID` AS `SERVICE_ID`,`service`.`SERVICE_NAME` AS `SERVICE_NAME` FROM `service` WHERE `service`.`SERVICE_ID` = ?]; nested exception is java.sql.sqlSyntaxErrorException: Table 'MysqLData.service' doesn't exist**

根据日志,我了解到它正在加载 oracle 驱动程序,但由于某些问题,它无法检索数据并将连接切换回 MysqL。由于 MysqL 没有这些表,因此抛出异常。

注意:

如果我将 oracle 更改为主,它会按预期工作。

解决方法

修改 IdentifierProcessing 以概括生成的 SQL