Spring Boot中JdbcTemplate多数据源配置
作者简介:大家好,我是撸代码的羊驼,前阿里巴巴架构师,现某互联网公司CTO
联系v:sulny_ann(17362204968),加我进群,大家一起学习,一起进步,一起对抗互联网寒冬
在《Spring Boot中JdbcTemplate源码分析》中讲到了自动配置相关的源代码实现。基于Spring Boot自动配置默认配置的组件,我们可以来自定义JdbcTemplate的实例化。而多数据源的配置就是在此基础上实例化多个数据源和JdbcTemplate。
下面,我们来看具体的源代码实现。
依赖类库
关于依赖类库与集成JdbcTemplate时的一样,Spring Boot版本2.2.2.RELEASE。
相关pom依赖如下:
<dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><!--数据库连接相关--><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-jdbc</artifactId></dependency><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId><optional>true</optional></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope><exclusions><exclusion><groupId>org.junit.vintage</groupId><artifactId>junit-vintage-engine</artifactId></exclusion></exclusions></dependency></dependencies>
spring-boot-starter-jdbc是集成jdbc的依赖,mysql-connector-java是基于mysql的依赖类库。lombok是简化代码的工具类,如果不需要可去掉,并去掉类中相关的注解。
spring-boot-starter-test为单元测试依赖的类库,这里单元测试使用的是junit5,注意使用方法与junit4差别比较大。
配置application
application.properties配置如下:???????
spring.datasource.primary.jdbc-url=jdbc:mysql://localhost:3306/spring?serverTimezone=UTC&useUnicode=true&characterEncoding=utf-8&useSSL=truespring.datasource.primary.username=rootspring.datasource.primary.password=root_123spring.datasource.primary.driver-class-name=com.mysql.cj.jdbc.Driverspring.datasource.secondary.jdbc-url=jdbc:mysql://localhost:3306/spring1?serverTimezone=UTC&useUnicode=true\&characterEncoding=utf-8&useSSL=truespring.datasource.secondary.username=rootspring.datasource.secondary.password=root_123spring.datasource.secondary.driver-class-name=com.mysql.cj.jdbc.Driver
既然是多数据源,肯定要配置多个数据源的配置。与单数据源配置基本形式差不多。
需要注意的是第一个配置项的key为:spring.datasource.primary.jdbc-url。与单数据源时使用的spring.datasource.url有所区别。不然,启动时会抛出异常。
多数据源对应的Java配置
下面就需要我们自己来实例化DataSource和JdbcTemplate。相关的实例化也可参看源码解析文章中Spring Boot的实例化方式。
这里,我们的实现如下:???????
@Configurationpublic class DataSourceConfig {@Primary@Bean(name = "primaryDataSource")@ConfigurationProperties(prefix="spring.datasource.primary")public DataSource primaryDataSource() {return DataSourceBuilder.create().build();}@Bean(name = "secondaryDataSource")@ConfigurationProperties(prefix="spring.datasource.secondary")public DataSource secondaryDataSource() {return DataSourceBuilder.create().build();}@Bean(name="primaryJdbcTemplate")public JdbcTemplate primaryJdbcTemplate (@Qualifier("primaryDataSource") DataSource dataSource ) {return new JdbcTemplate(dataSource);}@Bean(name="secondaryJdbcTemplate")public JdbcTemplate secondaryJdbcTemplate(@Qualifier("secondaryDataSource") DataSource dataSource) {return new JdbcTemplate(dataSource);}}
@Configuration声明该类为配置类。
@Primary指定当出现多个相同类型的实例化对象时,以该注解标注的为默认的。
@Bean实例化Bean,并将其注入到容器当中。这里分别实例化了primaryDataSource和secondaryDataSource两个DataSource,以Bean的名称来区分。
@ConfigurationProperties将前缀为spring.datasource.primary和前缀为spring.datasource.secondary的配置属性设置到对应的DataSource中。
随后实例化了两个JdbcTemplate,直接通过new关键字创建,并且把对应的DataSource作为构造参数传入。
经过该配置文件的配置,便有了两个JdbcTemplate。
实体类
实体类如下:???????
@Datapublic class Order {private int id;private String orderNo;private int amount;}
@Data为Lombok的注解,自动生成一些默认的方法,比如属性的getter/setter方法。
数据库
关于数据库的DDL如下:???????
CREATE TABLE `tb_order` (`id` int(11) NOT NULL AUTO_INCREMENT,`amount` int(11) NOT NULL DEFAULT '1',`order_no` varchar(64) NOT NULL DEFAULT '',PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=2 DEFAULT CHARSET=utf8
同样的表在两个数据库中进行创建。
接口定义
定义OrderService接口:???????
public interface OrderService {/*** 创建订单* @param order 订单信息* @return 记录数*/int save(Order order);/*** 保存到指定库* @param order 订单信息* @param jdbcTemplate jdbc* @return*/int save(Order order, JdbcTemplate jdbcTemplate);}
接口实现:???????
@Service("orderService")public class OrderServiceImpl implements OrderService {@Resource@Qualifier("primaryJdbcTemplate")private JdbcTemplate jdbcTemplate;@Overridepublic int save(Order order) {return jdbcTemplate.update("insert into tb_order(order_no, amount) values(?, ?)", order.getOrderNo(),order.getAmount());}@Overridepublic int save(Order order, JdbcTemplate secJdbcTemplate) {if (secJdbcTemplate != null) {return secJdbcTemplate.update("insert into tb_order(order_no, amount) values(?, ?)", order.getOrderNo(),order.getAmount());} else {return jdbcTemplate.update("insert into tb_order(order_no, amount) values(?, ?)", order.getOrderNo(),order.getAmount());}}}
在实现方法中,默认注入了主库的JdbcTemplate,同时在原来的save方法中新增了一个JdbcTemplate参数,可以根据是否传递该新的JdbcTemplate来决定使用哪个JdbcTemplate。
当然在此方法内也可以使用一个JdbcTemplate,然后根据参数动态的修改该JdbcTemplate指向的具体实现类。可以根据具体情况进行灵活运用。
单元测试
单元测试类如下:
@Slf4j@SpringBootTestclass OrderServiceTest {@Resourceprivate OrderService orderService;@Resource@Qualifier("primaryJdbcTemplate")private JdbcTemplate primaryJdbcTemplate;@Resource@Qualifier("secondaryJdbcTemplate")private JdbcTemplate secondaryJdbcTemplate;@Testvoid save() {Order order = new Order();order.setOrderNo("N003");order.setAmount(10000);orderService.save(order, primaryJdbcTemplate);orderService.save(order, secondaryJdbcTemplate);}}
执行以上单元测试,两个库中的tb_order表分别插入了一条数据。关于其他增删改查操作,可参考保存方法进行扩展。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!