mirror of
https://gitee.com/mybatis-flex/mybatis-flex.git
synced 2025-12-08 09:38:26 +08:00
commit
0631e8249d
@ -244,3 +244,46 @@ seata:
|
|||||||
|
|
||||||
[mybatis-flex-spring-boot-seata-demo](https://gitee.com/mybatis-flex/mybatis-flex-samples/tree/master/mybatis-flex-spring-boot-seata-demo) : Seata 官方 demo 与 flex 结合。
|
[mybatis-flex-spring-boot-seata-demo](https://gitee.com/mybatis-flex/mybatis-flex-samples/tree/master/mybatis-flex-spring-boot-seata-demo) : Seata 官方 demo 与 flex 结合。
|
||||||
|
|
||||||
|
|
||||||
|
## 子父线程同时访问一个ThreadLocal访问的场景
|
||||||
|
考虑到某些场景下,子父线程会同时访问父线程进行传递值进行切换数据源的场景,提供了以下的支持
|
||||||
|
比如如下的代码:
|
||||||
|
```java
|
||||||
|
public static void main(String[]args){
|
||||||
|
//线程1
|
||||||
|
//进行数据库操作读取 ds1
|
||||||
|
//切换数据源2
|
||||||
|
DataSourceKey.use("ds2");
|
||||||
|
new Thread(() -> {
|
||||||
|
//查询数据源 ds2
|
||||||
|
//实际在线程2并不是ds2而是ds1
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
此类场景进行如下的方案进行修改
|
||||||
|
1. 使用可以跨越线程池的`ThreadLocal`比如阿里的`transmittable-thread-local`
|
||||||
|
导入如下的包
|
||||||
|
```xml
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
<artifactId>transmittable-thread-local</artifactId>
|
||||||
|
<version>2.14.2</version>
|
||||||
|
</dependency>
|
||||||
|
```
|
||||||
|
2. 对切换的源码进行修改
|
||||||
|
```java
|
||||||
|
public static void main(String[]args){
|
||||||
|
DataSourceKey.setAnnotationKeyThreadLocal(new TransmittableThreadLocal<>());
|
||||||
|
DataSourceKey.setManualKeyThreadLocal(new TransmittableThreadLocal<>());
|
||||||
|
//线程1
|
||||||
|
//进行数据库操作读取 ds1
|
||||||
|
//切换数据源2
|
||||||
|
DataSourceKey.use("ds2");
|
||||||
|
new Thread(() -> {
|
||||||
|
//查询数据源 ds2
|
||||||
|
//实际在线程2使用的就是ds2
|
||||||
|
}).start();
|
||||||
|
}
|
||||||
|
```
|
||||||
|
### 扩展阅读
|
||||||
|
[transmittable-thread-local](https://github.com/alibaba/transmittable-thread-local) 可以不侵入进行代码原线程的替换
|
||||||
|
|||||||
@ -70,6 +70,7 @@
|
|||||||
<scope>compile</scope>
|
<scope>compile</scope>
|
||||||
<optional>true</optional>
|
<optional>true</optional>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
|
||||||
<!--optional end-->
|
<!--optional end-->
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
|
|||||||
@ -25,12 +25,12 @@ public class DataSourceKey {
|
|||||||
/**
|
/**
|
||||||
* 通过注解设置的 key
|
* 通过注解设置的 key
|
||||||
*/
|
*/
|
||||||
private static final ThreadLocal<String> annotationKeyThreadLocal = new ThreadLocal<>();
|
private static ThreadLocal<String> annotationKeyThreadLocal = new ThreadLocal<>();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 通过手动编码指定的 key
|
* 通过手动编码指定的 key
|
||||||
*/
|
*/
|
||||||
private static final ThreadLocal<String> manualKeyThreadLocal = new ThreadLocal<>();
|
private static ThreadLocal<String> manualKeyThreadLocal = new ThreadLocal<>();
|
||||||
|
|
||||||
public static String manualKey;
|
public static String manualKey;
|
||||||
|
|
||||||
@ -81,4 +81,11 @@ public class DataSourceKey {
|
|||||||
return key != null ? key : annotationKeyThreadLocal.get();
|
return key != null ? key : annotationKeyThreadLocal.get();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static void setAnnotationKeyThreadLocal(ThreadLocal<String> annotationKeyThreadLocal) {
|
||||||
|
DataSourceKey.annotationKeyThreadLocal = annotationKeyThreadLocal;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void setManualKeyThreadLocal(ThreadLocal<String> manualKeyThreadLocal) {
|
||||||
|
DataSourceKey.manualKeyThreadLocal = manualKeyThreadLocal;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -108,6 +108,12 @@
|
|||||||
<!-- <scope>test</scope>-->
|
<!-- <scope>test</scope>-->
|
||||||
<!-- </dependency>-->
|
<!-- </dependency>-->
|
||||||
|
|
||||||
|
<dependency>
|
||||||
|
<groupId>com.alibaba</groupId>
|
||||||
|
<artifactId>transmittable-thread-local</artifactId>
|
||||||
|
<version>2.14.2</version>
|
||||||
|
</dependency>
|
||||||
|
|
||||||
|
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.assertj</groupId>
|
<groupId>org.assertj</groupId>
|
||||||
|
|||||||
@ -0,0 +1,69 @@
|
|||||||
|
package com.mybatisflex.test;
|
||||||
|
|
||||||
|
import com.alibaba.ttl.TransmittableThreadLocal;
|
||||||
|
import com.mybatisflex.core.MybatisFlexBootstrap;
|
||||||
|
import com.mybatisflex.core.audit.AuditManager;
|
||||||
|
import com.mybatisflex.core.audit.ConsoleMessageCollector;
|
||||||
|
import com.mybatisflex.core.audit.MessageCollector;
|
||||||
|
import com.mybatisflex.core.datasource.DataSourceKey;
|
||||||
|
import com.mybatisflex.core.row.Db;
|
||||||
|
import com.mybatisflex.core.row.Row;
|
||||||
|
import com.mybatisflex.core.row.RowUtil;
|
||||||
|
import com.zaxxer.hikari.HikariDataSource;
|
||||||
|
import java.util.List;
|
||||||
|
import javax.sql.DataSource;
|
||||||
|
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseBuilder;
|
||||||
|
import org.springframework.jdbc.datasource.embedded.EmbeddedDatabaseType;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author life
|
||||||
|
*/
|
||||||
|
public class MultiThreadsTest {
|
||||||
|
|
||||||
|
public static void main(String[] args) {
|
||||||
|
DataSourceKey.setAnnotationKeyThreadLocal(new TransmittableThreadLocal<>());
|
||||||
|
DataSourceKey.setManualKeyThreadLocal(new TransmittableThreadLocal<>());
|
||||||
|
DataSource dataSource = new EmbeddedDatabaseBuilder()
|
||||||
|
.setType(EmbeddedDatabaseType.H2)
|
||||||
|
.setName("db1")
|
||||||
|
.addScript("schema.sql")
|
||||||
|
.addScript("data.sql")
|
||||||
|
.build();
|
||||||
|
|
||||||
|
HikariDataSource dataSource2 = new HikariDataSource();
|
||||||
|
dataSource2.setJdbcUrl("jdbc:mysql://127.0.0.1:3306/flex_test?characterEncoding=utf-8");
|
||||||
|
dataSource2.setUsername("root");
|
||||||
|
dataSource2.setPassword("131496");
|
||||||
|
|
||||||
|
MybatisFlexBootstrap.getInstance()
|
||||||
|
.setDataSource(dataSource)
|
||||||
|
.addMapper(AccountMapper.class)
|
||||||
|
.addDataSource("ds2", dataSource2)
|
||||||
|
.start();
|
||||||
|
|
||||||
|
//开启审计功能
|
||||||
|
AuditManager.setAuditEnable(true);
|
||||||
|
|
||||||
|
//设置 SQL 审计收集器
|
||||||
|
MessageCollector collector = new ConsoleMessageCollector();
|
||||||
|
AuditManager.setMessageCollector(collector);
|
||||||
|
|
||||||
|
//默认查询 db1
|
||||||
|
System.out.println("\n------ds1");
|
||||||
|
List<Row> rows1 = Db.selectAll(null, "tb_account");
|
||||||
|
RowUtil.printPretty(rows1);
|
||||||
|
|
||||||
|
System.out.println("\n------ds2");
|
||||||
|
DataSourceKey.use("ds2");
|
||||||
|
new Thread(() -> {
|
||||||
|
//查询数据源 ds2
|
||||||
|
System.out.println("\n------Thread-ds2");
|
||||||
|
List<Row> rows = Db.selectAll(null, "tb_account");
|
||||||
|
RowUtil.printPretty(rows);
|
||||||
|
}).start();
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
Loading…
x
Reference in New Issue
Block a user