简体   繁体   中英

How to specific default schema for MySQL db in Spring Boot Jdbc

We are connecting to multiple databases from Spring boot.

application.properties:

datasource.target.url=jdbc:mysql://localhost:3306/db_test_1?useSSL=false
datasource.target.driver-class-name=com.mysql.jdbc.Driver

datasource.origin.url=jdbc:mysql://localhost:3306/db_test_2?useSSL=false
datasource.origin.driver-class-name=com.mysql.jdbc.Driver

Database Config:

@Configuration
public class DatabaseConfig {

    @Bean(name = "originJdbcTemplate")
    public JdbcTemplate originJdbcTemplate() {
        return new JdbcTemplate(originDataSource());
    }

    @Bean(name = "targetJdbcTemplate")
    public JdbcTemplate targetJdbcTemplate() {
        return new JdbcTemplate(targetDataSource());
    }

    @Bean
    @Primary
    @ConfigurationProperties("datasource.origin")
    public DataSourceProperties originDataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean
    @Primary
    @ConfigurationProperties("datasource.origin")
    public DataSource originDataSource() {
        return originDataSourceProperties().initializeDataSourceBuilder().build();
    }

    @Bean
    @ConfigurationProperties("datasource.target")
    public DataSourceProperties targetDataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean
    @ConfigurationProperties("datasource.target")
    public DataSource targetDataSource() {
        return targetDataSourceProperties().initializeDataSourceBuilder().build();
    }

}

We are using Spring Jdbc template and we have to explicitly name the schema in each query even though we have defined the schema name in url above in application properties. eg: The query without schema name doesn't work

select * from db_test_1.user //works with schema name
select * from user //doesn't work

As per this SO Answer I should use Connection.setCatalog() , how do I do it in Spring configuration?

By using Delegating Datasource

class DefaultSchemaDelegatingDS extends DelegatingDataSource {
    private final String catalogName;

    public DefaultSchemaDelegatingDS(final String catalogName, final DataSource dataSource) {
        super(dataSource);
        this.catalogName = catalogName;
    }

    @Override
    public Connection getConnection() throws SQLException {
        final Connection connection = super.getConnection();
        connection.setCatalog(this.catalogName);
        return connection;
    }
}

and then in the DatabaseConfig

@Configuration
public class DatabaseConfig {

    @Value("${datasource.target.default_schema}")
    private String defaultTargetSchema;

    @Value("${datasource.origin.default_schema}")
    private String defaultOriginSchema;

    @Bean(name = "originJdbcTemplate")
    public JdbcTemplate originJdbcTemplate() {
        return new JdbcTemplate(originDataSource());
    }

    @Bean(name = "targetJdbcTemplate")
    public JdbcTemplate targetJdbcTemplate() {
        return new JdbcTemplate(targetDataSource());
    }

    @Bean
    @Primary
    @ConfigurationProperties("datasource.origin")
    public DataSourceProperties originDataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean
    @Primary
    @ConfigurationProperties("datasource.origin")
    public DataSource originDataSource() {
        final DataSource ds = originDataSourceProperties().initializeDataSourceBuilder().build();
        return new DefaultSchemaDelegatingDS(defaultOriginSchema, ds);
    }

    @Bean
    @ConfigurationProperties("datasource.target")
    public DataSourceProperties targetDataSourceProperties() {
        return new DataSourceProperties();
    }

    @Bean
    @ConfigurationProperties("datasource.target")
    public DataSource targetDataSource() {
        final DataSource ds = targetDataSourceProperties().initializeDataSourceBuilder().build();
        return new DefaultSchemaDelegatingDS(defaultTargetSchema, ds);
    }
}

The other way without using the DelegatingDatasource was to simply add

jdbcTemplate.getDataSource().getConnection().setCatalog(catalogName);

eg,

@Bean(name = "originJdbcTemplate")
public JdbcTemplate originJdbcTemplate() throws SQLException {
    JdbcTemplate jdbcTemplate = new JdbcTemplate(originDataSource());
    jdbcTemplate.getDataSource().getConnection().setCatalog(defaultOriginSchema);
    return jdbcTemplate;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM