SpringBoot动态数据源(多数据源⾃动切换)
本⽂实现案例场景:
某系统除了需要从⾃⼰的主要数据库上读取和管理数据外,还有⼀部分业务涉及到其他多个数据库,要求可以在任何⽅法上可以灵活指定具体要操作的数据库。
为了在开发中以最简单的⽅法使⽤,本⽂基于注解和AOP的⽅法实现,在spring boot框架的项⽬中,添加本⽂实现的代码类后,只需要配置好数据源就可以直接通过注解使⽤,简单⽅便。
⼀配置⼆使⽤ 1. 启动类注册动态数据源 2. 配置⽂件中配置多个数据源 3. 在需要的⽅法上使⽤注解指定数据源
1、在启动类添加 @Import({DynamicDataSourceRegister.class, MProxyTransactionManagementConfiguration.class})
1@SpringBootApplication
2@Import({DynamicDataSourceRegister.class}) // 注册动态多数据源
3public class SpringBootSampleApplication {
4
5 // 省略其他代码
6}
2、配置⽂件配置内容为:
(不包括项⽬中的其他配置,这⾥只是数据源相关的)
1# 主数据源,默认的
2spring.datasource.sql.jdbc.Driver
3spring.datasource.url=jdbc:mysql://localhost:3306/test
4spring.datasource.username=root
5spring.datasource.password=123456
6
7# 更多数据源
8custom.datasource.names=ds1,ds2
9custom.datasource.ds1.sql.jdbc.Driver
10custom.datasource.ds1.url=jdbc:mysql://localhost:3306/test1
11custom.datasource.ds1.username=root
12custom.datasource.ds1.password=123456
13
14custom.datasource.ds2.sql.jdbc.Driver
15custom.datasource.ds2.url=jdbc:mysql://localhost:3306/test2
16custom.datasource.ds2.username=root
17custom.datasource.ds2.password=123456
3、使⽤⽅法
1package org.springboot.sample.service;
2
3import java.sql.ResultSet;
4import java.sql.SQLException;
5import java.util.List;
6
7import org.springboot.sample.datasource.TargetDataSource;
8import org.ity.Student;
9import org.springboot.sample.mapper.StudentMapper;
10import org.springframework.beans.factory.annotation.Autowired;
11import org.JdbcTemplate;
12import org.RowMapper;
13import org.springframework.stereotype.Service;
14
15/**
16 * Student Service
17 *
18 * @author 单红宇(365384722)
18 * @author 单红宇(365384722)
19 * @myblog blog.csdn/catoop/
20 * @create 2016年1⽉12⽇
21 */
22@Service
23public class StudentService {
24
25 @Autowired
26 private JdbcTemplate jdbcTemplate;
27
28 // MyBatis的Mapper⽅法定义接⼝
29 @Autowired
30 private StudentMapper studentMapper;
31
32 @TargetDataSource(name="ds2")
33 public List<Student> likeName(String name){
34 return studentMapper.likeName(name);
35 }
36
37 public List<Student> likeNameByDefaultDataSource(String name){
38 return studentMapper.likeName(name);
39 }
40
41 /**
42 * 不指定数据源使⽤默认数据源
43 *
44 * @return
45 * @author SHANHY
46 * @create 2016年1⽉24⽇
47 */
48 public List<Student> getList(){
49 String sql = "SELECT ID,NAME,SCORE_SUM,SCORE_AVG, AGE FROM STUDENT";
50 return (List<Student>) jdbcTemplate.query(sql, new RowMapper<Student>(){
51
52 @Override
53 public Student mapRow(ResultSet rs, int rowNum) throws SQLException {
54 Student stu = new Student();
55 stu.Int("ID"));
56 stu.Int("AGE"));
57 stu.String("NAME"));
58 stu.String("SCORE_SUM"));
59 stu.String("SCORE_AVG"));
60 return stu;
61 }
62
63 });
64 }
65
66 /**
67 * 指定数据源
68 *
69 * @return
70 * @author SHANHY
71 * @create 2016年1⽉24⽇
72 */
73 @TargetDataSource(name="ds1")
74 public List<Student> getListByDs1(){
75 String sql = "SELECT ID,NAME,SCORE_SUM,SCORE_AVG, AGE FROM STUDENT";
76 return (List<Student>) jdbcTemplate.query(sql, new RowMapper<Student>(){
77
78 @Override
79 public Student mapRow(ResultSet rs, int rowNum) throws SQLException {
80 Student stu = new Student();
81 stu.Int("ID"));
82 stu.Int("AGE"));
83 stu.String("NAME"));
84 stu.String("SCORE_SUM"));
85 stu.String("SCORE_AVG"));
86 return stu;
87 }
88
89 });
90 }
91
92 /**
93 * 指定数据源
94 *
95 * @return
96 * @author SHANHY
97 * @create 2016年1⽉24⽇
98 */
99 @TargetDataSource(name="ds2")
100 public List<Student> getListByDs2(){
101 String sql = "SELECT ID,NAME,SCORE_SUM,SCORE_AVG, AGE FROM STUDENT";
102 return (List<Student>) jdbcTemplate.query(sql, new RowMapper<Student>(){
103
104 @Override
105 public Student mapRow(ResultSet rs, int rowNum) throws SQLException {
106 Student stu = new Student();
107 stu.Int("ID"));
108 stu.Int("AGE"));
109 stu.String("NAME"));
110 stu.String("SCORE_SUM"));
111 stu.String("SCORE_AVG"));
112 return stu;
113 }
114
115 });
116 }
117}
要注意的是,在使⽤MyBatis时,注解@TargetDataSource 不能直接在接⼝类Mapper上使⽤。 按上⾯的代码中StudentMapper为接⼝,代码如下:
1package org.springboot.sample.mapper;
2
3import java.util.List;
4
5import org.ity.Student;
6
7/**
8 * StudentMapper,映射SQL语句的接⼝,⽆逻辑实现
9 *
10 * @author 单红宇(365384722)
11 * @myblog blog.csdn/catoop/
12 * @create 2016年1⽉20⽇
13 */
14public interface StudentMapper {
15
16 // 注解 @TargetDataSource 不可以在这⾥使⽤
17 List<Student> likeName(String name);
18
19 Student getById(int id);
20
21 String getNameById(int id);
22
23}
请将下⾯⼏个类放到Spring Boot项⽬中。
DynamicDataSource.java
DynamicDataSourceAspect.java
DynamicDataSourceContextHolder.java
DynamicDataSourceRegister.java
TargetDataSource.java
1package org.springboot.sample.datasource;
2
3import org.springframework.jdbc.datasource.lookup.AbstractRoutingDataSource;
4
5/**
6 * 动态数据源
7 *
8 * @author 单红宇(365384722)
9 * @myblog blog.csdn/catoop/
10 * @create 2016年1⽉22⽇
11 */springboot aop
12public class DynamicDataSource extends AbstractRoutingDataSource {
13
14 @Override
15 protected Object determineCurrentLookupKey() {
16 DataSourceType();
17 }
18
19}
1package org.springboot.sample.datasource;
2
3import org.aspectj.lang.JoinPoint;
4import org.aspectj.lang.annotation.After;
5import org.aspectj.lang.annotation.Aspect;
6import org.aspectj.lang.annotation.Before;
7import org.slf4j.Logger;
8import org.slf4j.LoggerFactory;
9import org.springframework.stereotype.Component;
10
11/**
12 * 切换数据源Advice
13 *
14 * @author 单红宇(365384722)
15 * @myblog blog.csdn/catoop/
16 * @create 2016年1⽉23⽇
17 */
18@Aspect
19@Order(-1)// 保证该AOP在@Transactional之前执⾏
20@Component
21public class DynamicDataSourceAspect {
22
23 private static final Logger logger = Logger(DynamicDataSourceAspect.class); 24
25 @Before("@annotation(ds)")
26 public void changeDataSource(JoinPoint point, TargetDataSource ds) throws Throwable {
27 String dsId = ds.name();
28 if (!ainsDataSource(dsId)) {
29 ("数据源[{}]不存在,使⽤默认数据源 > {}", ds.name(), Signature());
30 } else {
31 logger.debug("Use DataSource : {} > {}", ds.name(), Signature());
32 DynamicDataSourceContextHolder.setDataSourceType(ds.name());
33 }
34 }
35
36 @After("@annotation(ds)")
37 public void restoreDataSource(JoinPoint point, TargetDataSource ds) {
38 logger.debug("Revert DataSource : {} > {}", ds.name(), Signature());
39 DynamicDataSourceContextHolder.clearDataSourceType();
40 }
41
42}
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论