Gitee地址:dynamic-datasource: 基于 SpringBoot 多数据源 动态数据源 主从分离 快速启动器 支持分布式事务
依赖
<dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.mybatis.spring.boot</groupId> <artifactId>mybatis-spring-boot-starter</artifactId> <version>3.0.3</version> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.33</version> </dependency> <!--dynamic-datasource --> <dependency> <groupId>com.baomidou</groupId> <artifactId>dynamic-datasource-spring-boot3-starter</artifactId> <version>4.3.1</version> </dependency> <dependency> <groupId>com.alibaba</groupId> <artifactId>druid-spring-boot-starter</artifactId> <version>1.2.21</version> </dependency>
application.properties
spring.application.name=dynamic-datasource server.port=8088 #设置默认的数据源或者数据源组,默认值即为master spring.datasource.dynamic.primary=master #严格匹配数据源,默认false. true未匹配到指定数据源时抛异常,false使用默认数据源 spring.datasource.dynamic.strict=false spring.datasource.dynamic.datasource.master.url=jdbc:mysql://localhost:3306/dy?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true spring.datasource.dynamic.datasource.master.username=root spring.datasource.dynamic.datasource.master.password=root spring.datasource.dynamic.datasource.master.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.dynamic.datasource.master.type=com.alibaba.druid.pool.DruidDataSource spring.datasource.dynamic.datasource.slave.url=jdbc:mysql://localhost2:3306/dy?useUnicode=true&characterEncoding=utf8&zeroDateTimeBehavior=convertToNull&useSSL=true&serverTimezone=GMT%2B8&autoReconnect=true&rewriteBatchedStatements=true spring.datasource.dynamic.datasource.slave.username=root spring.datasource.dynamic.datasource.slave.password=root spring.datasource.dynamic.datasource.slave.driver-class-name=com.mysql.cj.jdbc.Driver #去掉默认使用HikariCP spring.datasource.dynamic.datasource.slave.type=com.alibaba.druid.pool.DruidDataSource logging.level.com.example.dynamicdatasource=debug mybatis.type-aliases-package=com.example.dynamicdatasource.pojo mybatis.mapper-locations=classpath*:mappers/*Mapper.xml #驼峰 mybatis.configuration.map-underscore-to-camel-case=true
package com.example.dynamicdatasource.controller;
import com.example.dynamicdatasource.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author hrui
* @date 2024/8/6 15:49
*/
@RestController
public class ProductController {
@Autowired
private ProductService productService;
@GetMapping("/saveProduct")
public String saveProduct(){
productService.saveProduct();
return "saveProduct success";
}
}
package com.example.dynamicdatasource.controller;
import com.example.dynamicdatasource.service.TransactionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author hrui
* @date 2024/8/6 16:10
*/
@RestController
public class TransactionController {
@Autowired
private TransactionService transactionService;
@GetMapping("/trans")
public String saveUserAndProduct() {
transactionService.saveUserAndProduct();
return "success";
}
}
package com.example.dynamicdatasource.controller;
import com.example.dynamicdatasource.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* @author hrui
* @date 2024/8/6 15:49
*/
@RestController
public class UserController {
@Autowired
private UserService userService;
@GetMapping("/saveUser")
public String saveUser() {
userService.saveUser();
return "success";
}
}
package com.example.dynamicdatasource.service;
/**
* @author hrui
* @date 2024/8/6 15:49
*/
public interface ProductService {
void saveProduct();
}
package com.example.dynamicdatasource.service;
/**
* @author hrui
* @date 2024/8/6 16:11
*/
public interface TransactionService {
void saveUserAndProduct();
}
package com.example.dynamicdatasource.service;
/**
* @author hrui
* @date 2024/8/6 15:49
*/
public interface UserService {
void saveUser();
}
package com.example.dynamicdatasource.service.impl;
import com.example.dynamicdatasource.mapper.ProductMapper;
import com.example.dynamicdatasource.pojo.Product;
import com.example.dynamicdatasource.service.ProductService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
/**
* @author hrui
* @date 2024/8/6 15:49
*/
@Service
public class ProductServiceImpl implements ProductService {
@Autowired
private ProductMapper productMapper;
@Override
public void saveProduct() {
Product product = new Product();
product.setName("product");
product.setPrice(new BigDecimal(100));
int i=productMapper.saveProduct(product);
System.out.println(i>0?"插入成功":"插入失败");
}
}
package com.example.dynamicdatasource.service.impl;
import com.baomidou.dynamic.datasource.annotation.DSTransactional;
import com.example.dynamicdatasource.mapper.ProductMapper;
import com.example.dynamicdatasource.mapper.UserMapper;
import com.example.dynamicdatasource.pojo.Product;
import com.example.dynamicdatasource.pojo.User;
import com.example.dynamicdatasource.service.TransactionService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.math.BigDecimal;
/**
* @author hrui
* @date 2024/8/6 16:11
*/
@Service
public class TransactionServiceImpl implements TransactionService {
@Autowired
private UserMapper userMapper;
@Autowired
private ProductMapper productMapper;
@DSTransactional
//使用@Transaction时候 配置类启动类加 @TransactionServiceImpl 现在不加也行
//@Transactional//切换时候注意maven清理 这个注解此时不允许使用 报表不存在因数据源还在主库里 Table 'dy.t_product' doesn't exist
public void saveUserAndProduct() {
//判断是否开启事务
// if( TransactionSynchronizationManager.isActualTransactionActive()){
// System.out.println("开启事务");
// }else{
// System.out.println("未开启事务");
// }
User user = new User(null, "李四", "123456", 18, "男", "北京");
Product product = new Product(null, "手机", new BigDecimal(1000));
int i=userMapper.saveUser(user);
int i2=productMapper.saveProduct(product);
System.out.println(1/0);
System.out.println(i>0&&i2>0?"插入成功":"插入失败");
}
}
package com.example.dynamicdatasource.service.impl;
import com.example.dynamicdatasource.mapper.UserMapper;
import com.example.dynamicdatasource.pojo.User;
import com.example.dynamicdatasource.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* @author hrui
* @date 2024/8/6 15:49
*/
@Service
public class UserServiceImpl implements UserService {
@Autowired
private UserMapper userMapper;
@Override
public void saveUser() {
User user = new User(null, "张三", "123456", 18, "男", "北京");
int i=userMapper.saveUser(user);
System.out.println(i>0?"插入成功":"插入失败");
}
}
package com.example.dynamicdatasource.mapper;
import com.baomidou.dynamic.datasource.annotation.DS;
import com.example.dynamicdatasource.pojo.Product;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Options;
/**
* @author hrui
* @date 2024/8/6 15:50
*/
@DS("slave")
public interface ProductMapper {
@Insert("insert into t_product(name,price) values(#{name},#{price})")
//返回自增主键
@Options(useGeneratedKeys = true, keyProperty = "id")
int saveProduct(Product product);
}
package com.example.dynamicdatasource.mapper;
import com.example.dynamicdatasource.pojo.User;
import org.apache.ibatis.annotations.Insert;
import org.apache.ibatis.annotations.Options;
/**
* @author hrui
* @date 2024/8/6 15:50
*/
public interface UserMapper {
@Insert("insert into t_user(name,sex,age,address,password) values(#{name},#{sex},#{age},#{address},#{password})")
//返回自增主键
@Options(useGeneratedKeys = true, keyProperty = "id")
int saveUser(User user);
}
package com.example.dynamicdatasource.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
import java.math.BigDecimal;
/**
* @author hrui
* @date 2024/8/6 15:50
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Product {
private Integer id;
private String name;
private BigDecimal price;
}
package com.example.dynamicdatasource.pojo;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
/**
* @author hrui
* @date 2024/8/6 15:50
*/
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User {
private Integer id;
private String name;
private String password;
private Integer age;
private String sex;
private String address;
}