@DS多数据源baomidou的用法,事务处理
多数据源的使用
·
多数据源的使用场景:
1. 为了系统性能,数据库采用了读写分离,应用写主库,读从库
2. 项目业务有不同的数据库,比如电商系统,有用户库、商品库、交易库。
pom.xml配置:(注意版本号,低于这个版本可能会启动报错。。。被坑过)
我的springBoot版本是:2.3.0.RELEASE
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>dynamic-datasource-spring-boot-starter</artifactId>
<version>3.5.0</version>
</dependency>
springBoot的yml配置:
spring:
datasource:
druid: # Druid 【监控】相关的全局配置
web-stat-filter:
enabled: true
stat-view-servlet:
enabled: true
allow: # 设置白名单,不填则允许所有访问
url-pattern: /druid/*
login-username: admin # 控制台管理用户名和密码
login-password: 123456
filter:
stat:
enabled: true
log-slow-sql: true # 慢 SQL 记录
slow-sql-millis: 100
merge-sql: true
wall:
config:
multi-statement-allow: true
dynamic: # 多数据源配置
druid: # Druid 【连接池】相关的全局配置
initial-size: 5 # 初始连接数
min-idle: 10 # 最小连接池数量
max-active: 20 # 最大连接池数量
max-wait: 600000 # 配置获取连接等待超时的时间,单位:毫秒
time-between-eviction-runs-millis: 60000 # 配置间隔多久才进行一次检测,检测需要关闭的空闲连接,单位:毫秒
min-evictable-idle-time-millis: 300000 # 配置一个连接在池中最小生存的时间,单位:毫秒
max-evictable-idle-time-millis: 900000 # 配置一个连接在池中最大生存的时间,单位:毫秒
# validation-query: SELECT 1 FROM DUAL # 配置检测连接是否有效
test-while-idle: true
test-on-borrow: false
test-on-return: false
# 设置默认的数据源或者数据源组,默认值即为master
primary: userDb
datasource:
userDb:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://rm-1.mysql.rds.aliyuncs.com:3306/a?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
username: aa
password: bb
productDb:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://rm-2.mysql.rds.aliyuncs.com:3306/b?allowMultiQueries=true&useUnicode=true&characterEncoding=UTF-8&useSSL=false&serverTimezone=Asia/Shanghai
username: aa
password: bb
另外,如果有自己的Druid配置类,请注释,怕有冲突。我的就有,注释这个类就好了
测试实现类A:我采用@Ds注解在service方法上面
@Transactional //本类下面的所有方法开始事务机制
@Service(value = "userBaseInfoDynamic")
@DS("userDb")//这里用了 以下方法默认都是这个,方法也可以单独定义
public class UserBaseInfoDynamicImpl implements UserBaseInfoDynamic {
@Autowired
UserBaseInfoMapper userBaseInfoMapper;
@Resource
ShopItemInfoMapper shopItemInfoMapper;
@Resource(name = "userBaseInfoDynamicProduct")
UserBaseInfoDynamic userBaseInfoDynamicProduct;
@DS("userDb")
@Override
public String selectNickName(long userId) {
UserBaseInfo userBaseInfo = userBaseInfoMapper.selectByPrimaryKey(userId);
return userBaseInfo == null ? null : userBaseInfo.getNickName();
}
@DS("productDb")
@Override
public String selectProductName(long itemId) {
ShopItemInfo shopItemInfo = shopItemInfoMapper.selectByPrimaryKey(itemId);
return shopItemInfo == null ? null : shopItemInfo.getItemName();
}
@DS("productDb")
@Override
public boolean updateItem(long itemId,String itemName) {
ShopItemInfo shopItemInfo = new ShopItemInfo();
shopItemInfo.setId(itemId);
shopItemInfo.setItemName(itemName);
int i = shopItemInfoMapper.updateByPrimaryKeySelective(shopItemInfo);
return i == 1;
}
@DS("userDb")
@Override
public boolean updateItemUserDb(long itemId,String itemName) {
ShopItemInfo shopItemInfo = new ShopItemInfo();
shopItemInfo.setId(itemId);
shopItemInfo.setItemName(itemName);
int i = shopItemInfoMapper.updateByPrimaryKeySelective(shopItemInfo);
return i == 1;
}
@DS("userDb")
@Override
public boolean updateItemAll(long itemId,String itemName){
//以下要单独调用另外一个bean的方法,调用自己的没用,因为单个service的方法不支持垮数据源
System.out.println(userBaseInfoDynamicProduct.updateItem(itemId,itemName));
System.out.println(updateItemUserDb(itemId,itemName));
//int i = 1/0;
return true;
}
以上关键核心点:
userBaseInfoDynamicProduct.updateItem需要搞一个另外service封装调用,调用自己updateItem方法的没用,哪怕指定另外一个数据源,因为单个service方法里面不能垮数据源,只能通过另外的bean调用
测试实现类B:
@Transactional //本类下面的所有方法开始事务机制
@Service(value = "userBaseInfoDynamicProduct")
@DS("productDb")
public class UserBaseInfoDynamicImplProduct implements UserBaseInfoDynamic {
@Autowired
UserBaseInfoMapper userBaseInfoMapper;
@Resource
ShopItemInfoMapper shopItemInfoMapper;
@DS("productDb")
@Override
public String selectNickName(long userId) {
UserBaseInfo userBaseInfo = userBaseInfoMapper.selectByPrimaryKey(userId);
return userBaseInfo == null ? null : userBaseInfo.getNickName();
}
@DS("productDb")
@Override
public String selectProductName(long itemId) {
ShopItemInfo shopItemInfo = shopItemInfoMapper.selectByPrimaryKey(itemId);
return shopItemInfo == null ? null : shopItemInfo.getItemName();
}
@DS("productDb")
@Override
public boolean updateItem(long itemId,String itemName) {
ShopItemInfo shopItemInfo = new ShopItemInfo();
shopItemInfo.setId(itemId);
shopItemInfo.setItemName(itemName);
int i = shopItemInfoMapper.updateByPrimaryKeySelective(shopItemInfo);
return i == 1;
}
@Override
public boolean updateItemUserDb(long itemId, String itemName) {
return false;
}
@Override
public boolean updateItemAll(long itemId, String itemName) {
return false;
}
}
接口:
public interface UserBaseInfoDynamic {
String selectNickName(long userId);
String selectProductName(long itemId);
boolean updateItem(long itemId,String itemName);
boolean updateItemUserDb(long itemId,String itemName);
boolean updateItemAll(long itemId,String itemName);
}
单元测试:
@RunWith(SpringJUnit4ClassRunner.class)
@SpringBootTest(classes = CarownerhomeWxMiniprogramApplication.class)
public class UserBaseInfoServiceDynamicTest {
@Resource(name = "userBaseInfoDynamic")
UserBaseInfoDynamic userBaseInfoDynamic;
@Resource(name = "userBaseInfoDynamicProduct")
UserBaseInfoDynamic userBaseInfoDynamicProduct;
@Resource
BusinessTypeInfoService businessTypeInfoService;
@Test
public void testDynamic() {
String nickName = userBaseInfoDynamic.selectNickName(10001);
System.out.println("从user库获取的昵称:"+nickName);
String productName = userBaseInfoDynamic.selectProductName(1028);
System.out.println("从user库获取的商品名称:"+productName);
String nickName2 = userBaseInfoDynamicProduct.selectNickName(10001);
System.out.println("从product库获取的昵称:"+nickName2);
String productName2 = userBaseInfoDynamicProduct.selectProductName(1028);
System.out.println("从product库获取的商品名称:"+productName2);
List<BusinessTypeInfo> businessTypeInfos = businessTypeInfoService.selectList(1001l);
System.out.println("商家类型:"+businessTypeInfos.get(0).getBusinessTypeName());
userBaseInfoDynamic.updateItemAll(1028,"测试多数据源事务商品");
}
}
DSTransactional使用场景:如果一个service方法里面调用两个不同mapper的数据源(@DS在mapper类上面)
/**这里如果用@Transactional,
那么slaveMapper还是访问的masterMapper初次的数据源
**/
@DSTransactional
public void Add(){
User user = new User();
user.setUsername("张三");
user.setPassword("123456");
masterMapper.insertUser(user);
Role role = new Role();
role.setRole("管理员");
slaveMapper.insertRole(role);
}
@Mapper
@DS("master")
public interface MasterMapper {
int insertUser(User user);
}
@Mapper
@DS("slave")
public interface SlaveMapper {
int insertRole(Role role);
}
更多推荐
已为社区贡献1条内容
所有评论(0)