Skip to content

Commit b1e6b35

Browse files
committed
解决版本升级后启动报错的问题,留下一个历史遗留问题任没解决: 多数据源切换的事务问题
1 parent a72d15f commit b1e6b35

File tree

8 files changed

+73
-39
lines changed

8 files changed

+73
-39
lines changed

Diff for: Spring-Boot-MultiDS2-Switch/src/main/java/com/example/multidatasource/controller/DataSourceController.java

+17-5
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,9 @@
22

33
import com.example.multidatasource.service.StudentService;
44
import org.springframework.beans.factory.annotation.Autowired;
5-
import org.springframework.web.bind.annotation.RequestMapping;
5+
import org.springframework.web.bind.annotation.GetMapping;
6+
import org.springframework.web.bind.annotation.PathVariable;
7+
import org.springframework.web.bind.annotation.PostMapping;
68
import org.springframework.web.bind.annotation.RestController;
79

810
import java.util.List;
@@ -20,13 +22,23 @@ public DataSourceController(StudentService studentService) {
2022
this.studentService = studentService;
2123
}
2224

23-
@RequestMapping("/querystudentsfromoracle")
25+
@GetMapping("/querystudentsfromoracle")
2426
public List<Map<String, Object>> queryStudentsFromOracle() {
25-
return this.studentService.getAllStudentsFromSlave();
27+
return studentService.getAllStudentsFromSlave();
2628
}
2729

28-
@RequestMapping("/querystudentsfrommysql")
30+
@PostMapping("/updateStudent/{sno}/{sname}")
31+
public String updateStudent(@PathVariable("sno") int sno, @PathVariable("sname") String sname) {
32+
int i = studentService.updateStudent(sno, sname);
33+
if (i == -1) {
34+
return "failure";
35+
} else {
36+
return "success";
37+
}
38+
}
39+
40+
@GetMapping("/querystudentsfrommysql")
2941
public List<Map<String, Object>> queryStudentsFromMysql() {
30-
return this.studentService.getAllStudentsFromMaster();
42+
return studentService.getAllStudentsFromMaster();
3143
}
3244
}

Diff for: Spring-Boot-MultiDS2-Switch/src/main/java/com/example/multidatasource/dao/StudentMapper.java

+2
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.example.multidatasource.dao;
22

33
import org.apache.ibatis.annotations.Mapper;
4+
import org.apache.ibatis.annotations.Param;
45
import org.springframework.stereotype.Repository;
56

67
import java.util.List;
@@ -13,4 +14,5 @@
1314
@Mapper
1415
public interface StudentMapper {
1516
List<Map<String, Object>> getAllStudents();
17+
int updateStudent(@Param("sno") int sno, @Param("sname") String sname);
1618
}

Diff for: Spring-Boot-MultiDS2-Switch/src/main/java/com/example/multidatasource/datasourceConfig/DynamicDataSource.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ public class DynamicDataSource extends AbstractRoutingDataSource {
1515
protected Object determineCurrentLookupKey() {
1616
/*
1717
* DynamicDataSourceContextHolder代码中使用setDataSourceType 设置当前的数据源,
18-
* 在路由类中使用getDataSourceType进行获取,交给AbstractRoutingDataSource进行注入使用
18+
* 在路由类中使用getDataSourceType进行获取,交给AbstractRoutingDataSource进行注入使用
1919
*/
2020
return DynamicDataSourceContextHolder.getDataSourceType();
2121
}

Diff for: Spring-Boot-MultiDS2-Switch/src/main/java/com/example/multidatasource/datasourceConfig/DynamicDataSourceAspect.java

+14-8
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,8 @@
44
import org.aspectj.lang.annotation.After;
55
import org.aspectj.lang.annotation.Aspect;
66
import org.aspectj.lang.annotation.Before;
7+
import org.slf4j.Logger;
8+
import org.slf4j.LoggerFactory;
79
import org.springframework.core.Ordered;
810
import org.springframework.core.annotation.Order;
911
import org.springframework.stereotype.Component;
@@ -13,9 +15,13 @@
1315
* Created by dengzhiming on 2019/3/29
1416
*/
1517
@Aspect
16-
@Order(Ordered.HIGHEST_PRECEDENCE)//保证该AOP在@Transactional之前执行
18+
//1.保证该AOP在@Transactional之前执行;
19+
//2.保证拦截器ExposeInvocationInterceptor在拦截链开头,其优先级为HIGHEST_PRECEDENCE+1
20+
@Order(Ordered.HIGHEST_PRECEDENCE + 2)
1721
@Component
1822
public class DynamicDataSourceAspect {
23+
private Logger log = LoggerFactory.getLogger(this.getClass());
24+
1925
/*
2026
* @Before("@annotation(ds)")的意思是:
2127
* @Before:在方法执行之前进行执行:
@@ -25,20 +31,20 @@ public class DynamicDataSourceAspect {
2531
public void changeDataSource(JoinPoint point, TargetDataSource targetDataSource) throws Throwable {
2632
//获取当前的指定的数据源;
2733
String dsId = targetDataSource.value();
28-
//如果不在我们注入的所有的数据源范围之内,那么输出警告信息,系统自动使用默认的数据源。
34+
//如果不在配置的数据源范围之内,则输出警告信息,且系统自动使用默认的数据源
2935
if (!DynamicDataSourceContextHolder.containsDataSource(dsId)) {
30-
System.err.println("数据源[{}]不存在,使用默认数据源 > {}" + targetDataSource.value() + point.getSignature());
36+
log.info("数据源[{}]不存在,使用默认数据源 > {}", targetDataSource.value(), point.getSignature());
3137
} else {
32-
System.out.println("Use DataSource : {} > {}" + targetDataSource.value() + point.getSignature());
33-
//找到的话那么设置到动态数据源上下文中
34-
DynamicDataSourceContextHolder.setDataSourceType(targetDataSource.value());
38+
log.info("Use DataSource : {} > {}", targetDataSource.value(), point.getSignature());
39+
//找到的话,那么设置到动态数据源上下文中
40+
DynamicDataSourceContextHolder.setDataSourceType(dsId);
3541
}
3642
}
3743

3844
@After("@annotation(targetDataSource)")
3945
public void restoreDataSource(JoinPoint point, TargetDataSource targetDataSource) {
40-
System.out.println("Revert DataSource : {} > {}" + targetDataSource.value() + point.getSignature());
41-
//方法执行完毕之后销毁当前数据源信息进行垃圾回收
46+
log.info("Revert DataSource : {} > {}", targetDataSource.value(), point.getSignature());
47+
//方法执行完毕之后,销毁当前数据源信息,进行垃圾回收
4248
DynamicDataSourceContextHolder.clearDataSourceType();
4349
}
4450
}

Diff for: Spring-Boot-MultiDS2-Switch/src/main/java/com/example/multidatasource/datasourceConfig/DynamicDataSourceRegister.java

+19-20
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@
66
import org.springframework.boot.context.properties.bind.Bindable;
77
import org.springframework.boot.context.properties.bind.Binder;
88
import org.springframework.boot.context.properties.source.ConfigurationPropertyName;
9-
import org.springframework.boot.context.properties.source.ConfigurationPropertyNameAliases;
109
import org.springframework.boot.context.properties.source.ConfigurationPropertySource;
1110
import org.springframework.boot.context.properties.source.MapConfigurationPropertySource;
1211
import org.springframework.context.EnvironmentAware;
1312
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
1413
import org.springframework.core.env.Environment;
1514
import org.springframework.core.type.AnnotationMetadata;
15+
import org.springframework.util.StringUtils;
1616

1717
import javax.sql.DataSource;
1818
import java.util.HashMap;
@@ -24,22 +24,13 @@
2424
*/
2525
public class DynamicDataSourceRegister implements ImportBeanDefinitionRegistrar, EnvironmentAware {
2626

27-
//指定默认数据源(springboot2.0默认数据源是hikari如何想使用其他数据源可以自己配置)
27+
//指定默认数据源(springboot2.0默认数据源是hikari如果想使用其他数据源可以自己配置)
2828
private static final String DATASOURCE_TYPE_DEFAULT = "com.zaxxer.hikari.HikariDataSource";
2929
//默认数据源
3030
private DataSource defaultDataSource;
3131
//用户自定义数据源
3232
private Map<String, DataSource> slaveDataSources = new HashMap<>();
3333

34-
private final static ConfigurationPropertyNameAliases aliases = new ConfigurationPropertyNameAliases(); //别名
35-
36-
static {
37-
//由于部分数据源配置不同,所以在此处添加别名,避免切换数据源出现某些参数无法注入的情况
38-
aliases.addAliases("url", "jdbc-url");
39-
aliases.addAliases("username", "user");
40-
}
41-
42-
4334
@Override
4435
public void setEnvironment(Environment environment) {
4536
initDefaultDataSource(environment);
@@ -49,14 +40,14 @@ public void setEnvironment(Environment environment) {
4940
private void initDefaultDataSource(Environment env) {
5041
// 读取主数据源
5142
Binder binder = Binder.get(env);
52-
Map dsMap = binder.bind("spring.datasource.druid.master", Map.class).get();
43+
Map dsMap = binder.bind("spring.datasource.druid.master", HashMap.class).get();
5344
defaultDataSource = buildDataSource(dsMap);
5445
}
5546

5647
private void initslaveDataSources(Environment env) {
5748
// 读取配置文件获取更多数据源
5849
Binder binder = Binder.get(env);
59-
HashMap map = binder.bind("spring.datasource.druid.slave", HashMap.class).get();
50+
Map map = binder.bind("spring.datasource.druid.slave", HashMap.class).get();
6051
for (Object o : map.entrySet()) {
6152
Map.Entry entry = (Map.Entry) o;
6253
String dsPrefix = (String) entry.getKey();
@@ -68,9 +59,9 @@ private void initslaveDataSources(Environment env) {
6859

6960
@Override
7061
public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanDefinitionRegistry beanDefinitionRegistry) {
71-
Map<Object, Object> targetDataSources = new HashMap<>();
62+
Map<String, DataSource> targetDataSources = new HashMap<>();
7263
//添加默认数据源
73-
targetDataSources.put("dataSource", this.defaultDataSource);
64+
targetDataSources.put("dataSource", defaultDataSource);
7465
DynamicDataSourceContextHolder.dataSourceIds.add("dataSource");
7566
//添加其他数据源
7667
targetDataSources.putAll(slaveDataSources);
@@ -85,17 +76,25 @@ public void registerBeanDefinitions(AnnotationMetadata annotationMetadata, BeanD
8576
mpv.addPropertyValue("targetDataSources", targetDataSources);
8677
//注册 - BeanDefinitionRegistry
8778
beanDefinitionRegistry.registerBeanDefinition("dataSource", beanDefinition);
79+
/*for (String key : slaveDataSources.keySet()) {
80+
GenericBeanDefinition transactionManagerDefinition = new GenericBeanDefinition();
81+
transactionManagerDefinition.setBeanClass(DataSourceTransactionManager.class);
82+
transactionManagerDefinition.setSynthetic(true);
83+
MutablePropertyValues propertyValues = transactionManagerDefinition.getPropertyValues();
84+
propertyValues.addPropertyValue("dataSource", slaveDataSources.get(key));
85+
beanDefinitionRegistry.registerBeanDefinition(key + "TransactionManager",transactionManagerDefinition);
86+
}*/
8887
}
8988

9089
private DataSource buildDataSource(Map dataSourceMap) {
9190
try {
92-
Object type = dataSourceMap.get("type");
93-
if (type == null) {
94-
type = DATASOURCE_TYPE_DEFAULT;// 默认DataSource
91+
String type = dataSourceMap.get("type").toString();
92+
if (StringUtils.isEmpty(type)) {
93+
type = DATASOURCE_TYPE_DEFAULT;
9594
}
96-
Class<? extends DataSource> dataSourceType = (Class<? extends DataSource>) Class.forName((String) type);
95+
Class<? extends DataSource> dataSourceType = (Class<? extends DataSource>) Class.forName(type);
9796
ConfigurationPropertySource source = new MapConfigurationPropertySource(dataSourceMap);
98-
Binder binder = new Binder(source.withAliases(aliases));
97+
Binder binder = new Binder(source);
9998
//通过类型绑定参数并获得实例对象
10099
return binder.bind(ConfigurationPropertyName.EMPTY, Bindable.of(dataSourceType)).get();
101100
} catch (ClassNotFoundException e) {

Diff for: Spring-Boot-MultiDS2-Switch/src/main/java/com/example/multidatasource/service/StudentService.java

+3-1
Original file line numberDiff line numberDiff line change
@@ -10,4 +10,6 @@ public interface StudentService {
1010
List<Map<String, Object>> getAllStudentsFromMaster();
1111

1212
List<Map<String, Object>> getAllStudentsFromSlave();
13-
}
13+
14+
int updateStudent(int sno,String sname);
15+
}

Diff for: Spring-Boot-MultiDS2-Switch/src/main/java/com/example/multidatasource/service/impl/StudentServiceImpl.java

+13-3
Original file line numberDiff line numberDiff line change
@@ -23,14 +23,24 @@ public StudentServiceImpl(StudentMapper studentMapper) {
2323
}
2424

2525
@Override
26+
@Transactional
2627
public List<Map<String, Object>> getAllStudentsFromMaster() {
27-
return this.studentMapper.getAllStudents();
28+
return studentMapper.getAllStudents();
2829
}
2930

3031
@Override
3132
@TargetDataSource("ds1")
32-
@Transactional
3333
public List<Map<String, Object>> getAllStudentsFromSlave() {
34-
return this.studentMapper.getAllStudents();
34+
return studentMapper.getAllStudents();
35+
}
36+
37+
@Override
38+
@TargetDataSource("ds1")
39+
@Transactional
40+
public int updateStudent(int sno, String sname) {
41+
int i = -1;
42+
i = studentMapper.updateStudent(sno, sname);
43+
int j = 1/0;
44+
return i;
3545
}
3646
}

Diff for: Spring-Boot-MultiDS2-Switch/src/main/resources/mapper/StudentMapper.xml

+4-1
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,7 @@
55
<select id="getAllStudents" resultType="java.util.Map">
66
select * from student
77
</select>
8-
</mapper>
8+
<update id="updateStudent">
9+
update student set sname = #{sname} where sno = #{sno}
10+
</update>
11+
</mapper>

0 commit comments

Comments
 (0)