多数据源配置及使用,在同一个方法下切换数据源。
切换数据源方法:
1. 通过注解切换数据源,可以在方法上使用也可以在类上使用,遵循就近原则
@DS(“数据源名”)
注意:在同一个方法使用多个数据源不要使用@Transactional,会导致报错。
2. 方法中手动切换
切换数据源类似压栈,弹栈操作。引入依赖和配置文件见示例。
//引入jar包
import com.baomidou.dynamic.datasource.toolkit.DynamicDataSourceContextHolder;
@Override
public OperaResponse testSelectCompanyAndUser() {
//方法体内部
//切换数据源
DynamicDataSourceContextHolder.push("mysql1");
//数据操作
//释放数据源
DynamicDataSourceContextHolder.poll();
//切换数据源
DynamicDataSourceContextHolder.push("mysql2");
//数据操作
//释放数据源
DynamicDataSourceContextHolder.poll();
return OperaResponse.ok();
}
示例使用场景,使用方法1
将测试服务器的企业与用户的关联关系映射到本地服务器中。
本例在mapper类上使用@DS切换数据源
引入依赖
<properties>
<dynamic-datasource.version>3.5.0</dynamic-datasource.version>
</properties>
<!-- Mybatis-plus多数据源 -->
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>${dynamic-datasource.version}</version>
</dependency>
配置文件yml
datasource:
dynamic:
primary: mysql1 #设置默认的数据源或者数据源组,默认值即为mysql1
strict: false #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源
datasource:
mysql1: # 数据源名
driverClassName: com.mysql.cj.jdbc.Driver
url: 数据源地址?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true
username: 用户名
password: 密码
mysql2: # 数据源名
driverClassName: com.mysql.cj.jdbc.Driver
url: 数据源地址?useUnicode=true&characterEncoding=utf8&useSSL=false&serverTimezone=GMT%2B8&allowPublicKeyRetrieval=true
username: 用户名
password: 密码
# 以下非必须,配置数据库连接池
type: com.zaxxer.hikari.HikariDataSource
hikari:
connection-timeout: 30000 # 等待连接池分配连接的最大时长(毫秒),超过这个时长还没可用的连接则发生SQLException, 默认:30秒
minimum-idle: 5 # 最小连接数
maximum-pool-size: 20 # 最大连接数
auto-commit: true # 自动提交
idle-timeout: 600000 # 连接超时的最大时长(毫秒),超时则被释放(retired),默认:10分钟
pool-name: DateSourceHikariCP # 连接池名字
max-lifetime: 1800000 # 连接的生命时长(毫秒),超时而且没被使用则被释放(retired),默认:30分钟 1800000ms
connection-test-query: SELECT 1
Mapper.java
@Repository
@DS("mysql2")
public interface CompanyUserMapper extends BaseMapper<CompanyUser> {
}
UserService.java
public interface IUserService extends IService<User> {
/**
* 将测试服务器的企业与用户的关联关系映射到本地服务器中
*
* 多数据源中@Transactional(rollbackFor = Exception.class) 事务失效并会导致切换数据源报错
* @DS("mysql1"),@DS("mysql1")切换数据源可以在方法上使用,也可以在类上使用。
* 如在mapper类或方法上使用,或在serviceImpl类或方法上使用。
* @return
*/
OperaResponse CompanyAndUserMapping();
}
UserServiceImpl.java
@Slf4j
@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements IUserService {
@Autowired
private CompanyUserMapper companyUserMapper;
@Override
public OperaResponse CompanyAndUserMapping() {
//查询所有企业部门用户信息
List<CompanyUser> companyUserList = companyUserMapper.selectList(new QueryWrapper<>());
//将企业部门用户信息根据用户id进行分组
Map<Long, List<CompanyUser>> map = companyUserList.stream().collect(Collectors.groupingBy(CompanyUser::getUserId));
List<User> userList = this.list();
//将企业id映射到用户表中
for(User user : userList){
if(map.containsKey(user.getId())){
List<CompanyUser> companyUserList1 = map.get(user.getId());
if(CollectionUtils.isEmpty(companyUserList1)){
return OperaResponse.error(ErrStatus.ERR_COMPANY);
}
if(companyUserList1.size() > 1){
log.info("用户id为:" + user.getId() + "的用户存在多个企业。"+"企业信息为:"+ companyUserList1.toString());
}
user.setCompanyId(companyUserList1.get(0) == null ? null : companyUserList1.get(0).getCompanyId());
//更新用户信息
this.updateById(user);
}
}
return OperaResponse.ok();
}
}
UserController.java
@RestController
@RequestMapping("/management/user")
public class UserController {
@Autowired
private IUserService userService;
/**
* 将测试服务器的企业与用户的关联关系映射到本地服务器中
*
* 多数据源中@Transactional(rollbackFor = Exception.class) 事务失效并会导致切换数据源报错
* @DS("mysql1"),@DS("mysql1")切换数据源可以在方法上使用,也可以在类上使用。
* 如在mapper类或方法上使用,或在serviceImpl类或方法上使用。
* @return
*/
@GetMapping("/CompanyAndUserMapping")
@WebLog(description = "映射企业与用户关系")
public OperaResponse CompanyAndUserMapping(){
return userService.CompanyAndUserMapping();
}
}