数据源简单配置应用
1.spring webflux + r2dbc 多数据源配置
项目中有时需要配置多个数据源,以下是一个简单配置使用,db1 作为默认数据源,可以使用spring JPA 查询,也可以配置dbclient, 执行自定义sql 查询,db2需要配置dbclient 使用。
配置文件
spring:r2dbc:db1:url: r2dbc:mysql://xxx.xxx.xxx.xxx/xxx_dbusername: xxpassword: *************db2:url: r2dbc:mysql://xxx.xxx.xxx.xxx/xxx_dbusername: xxxxxpassword: *******************
数据源设置
@Configuration
public class R2dbcConfig {@Bean@ConfigurationProperties(prefix = "spring.r2dbc.db1")public R2dbcProperties primaryR2dbcProperties() {return new R2dbcProperties();}@Bean@ConfigurationProperties(prefix = "spring.r2dbc.db2")public R2dbcProperties db2R2dbcProperties() {return new R2dbcProperties();}//默认为主数据源@Primary@Bean(name = "primaryConnectionFactory")public ConnectionFactory primaryConnectionFactory(@Qualifier("primaryR2dbcProperties") R2dbcProperties properties) {return createConnectionFactory(properties);}@Bean(name = "db2ConnectionFactory")public ConnectionFactory db2ConnectionFactory(@Qualifier("db2R2dbcProperties") R2dbcProperties properties) {return createConnectionFactory(properties);}private ConnectionFactory createConnectionFactory(R2dbcProperties properties) {return ConnectionFactories.get(ConnectionFactoryOptions.parse(properties.getUrl()).mutate().option(USER, properties.getUsername()).option(PASSWORD, properties.getPassword()).build());}@Primary@Bean(name = "primaryTransactionManager")public R2dbcTransactionManager primaryTransactionManager(@Qualifier("primaryConnectionFactory") ConnectionFactory connectionFactory) {return new R2dbcTransactionManager(connectionFactory);}@Bean(name = "db2TransactionManager")public R2dbcTransactionManager secondaryTransactionManager(@Qualifier("db2ConnectionFactory") ConnectionFactory connectionFactory) {return new R2dbcTransactionManager(connectionFactory);}@Primary@Bean("primaryDatabaseClient")public DatabaseClient mysqlDatabaseClient(@Qualifier("primaryConnectionFactory") ConnectionFactory connectionFactory) {return DatabaseClient.create(connectionFactory);}@Bean("db2DatabaseClient")public DatabaseClient db2DatabaseClient(@Qualifier("db2ConnectionFactory") ConnectionFactory connectionFactory) {return DatabaseClient.create(connectionFactory);}
}
Db2查询示例
@Service
@Slf4j
public class Db2QueryUtil {private static DatabaseClient dbClient;@Autowiredpublic Db2QueryUtil(@Qualifier(value ="db2DatabaseClient") DatabaseClient _dbClient) {dbClient = _dbClient;}public static <T> Flux<T> querMany(String sql, Class<T> aClass){return dbClient.sql(sql).map(row -> JSONObject.parseObject(row.toString(),aClass)).all().publishOn(Schedulers.boundedElastic());}}
2. JdbcTemplate 数据源配置
public class DataSourceConfig {private String dataSourceName;private String url;private String username;private String password;private String driver;
}@Component
public class DataSourceFactory {private final Map<String, JdbcTemplate> jdbcTemplateCache = new ConcurrentHashMap<>();private final Map<String, AtomicInteger> referenceCount = new ConcurrentHashMap<>();// 创建JdbcTemplatepublic synchronized JdbcTemplate getJdbcTemplate(DataSourceConfig config) {String CacheKey = config.getDataSourceName();referenceCount.computeIfAbsent(CacheKey, k -> new AtomicInteger(0)).incrementAndGet();if(jdbcTemplateCache.containsKey(CacheKey)&&jdbcTemplateCache.get(CacheKey)!=null) {return jdbcTemplateCache.get(CacheKey);}else{HikariDataSource dataSource = new HikariDataSource();dataSource.setJdbcUrl(config.getUrl());dataSource.setDriverClassName(config.getDriver());dataSource.setUsername(config.getUsername());dataSource.setPassword(config.getPassword());JdbcTemplate jdbcTemplate = new JdbcTemplate(dataSource);jdbcTemplateCache.put(CacheKey, jdbcTemplate);return jdbcTemplate;}}//关闭连接:避免使用中连接关闭,使用了计数器;computeIfPresent 避免重复关闭public void close(DataSourceConfig config){String cacheKey = config.getDataSourceName();AtomicInteger count = referenceCount.get(cacheKey);if (count != null && count.decrementAndGet() == 0) {jdbcTemplateCache.computeIfPresent(cacheKey, (key, jdbcTemplate) -> {try {DataSource dataSource = jdbcTemplate.getDataSource();if (dataSource instanceof HikariDataSource) {((HikariDataSource) dataSource).close();log.info("Successfully closed HikariDataSource: {}",config.getDataSourceName());} else {log.warn("Data source {} is not a HikariDataSource and cannot be closed", config.getDataSourceName());}} catch (Exception e) {log.error("Error closing data source: {} ",config.getDataSourceName(), e);}return null; // 从缓存中移除});}}}@Service
@Slf4j
public class DataSourceService {@Autowiredprivate DataSourceFactory dataSourceFactory;private List<Map<String, Object>> executeQuery(DataSourceConfig config, String sql, Object... params) {JdbcTemplate jdbcTemplate = dataSourceFactory.getJdbcTemplate(config);try {return jdbcTemplate.queryForList(sql, params);} catch (DataAccessException e) {throw new RuntimeException("SQL执行失败: ", e);}finally {dataSourceFactory.close(config);}}}
JdbcTemplate 可以依据用户传入不同 DataSourceConfig,实现多数据源查询,注:需要引入相关数据源jar包。