前言:
本章案例利用dynamic-datasource-spring-boot-starter集成多數據源,mybaits-plus采用3.3.0版本,主要講述配置多數據源,其案例中也包含了邏輯刪除、攻擊SQL阻斷解析器、p6spySQL性能分析打印、事務以及分頁和樂觀鎖插件。
dynamic-datasource-spring-boot-starter 是一個基於springboot的快速集成多數據源的啟動器,其支持 Jdk 1.7+, SpringBoot 1.4.x 1.5.x 2.0.x。
一、pom.xml
<!--代碼簡化,工具相關 --> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> <!--SQLServer 驅動--> <dependency> <groupId>com.microsoft.sqlserver</groupId> <artifactId>sqljdbc4</artifactId> <version>4.0</version> <scope>runtime</scope> </dependency> <!--mysql 驅動--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <scope>runtime</scope> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.3.0</version> </dependency> <dependency> <groupId>com.baomidou</groupId> <artifactId>dynamic-datasource-spring-boot-starter</artifactId> <version>2.4.2</version> </dependency> <dependency> <groupId>p6spy</groupId> <artifactId>p6spy</artifactId> <version>3.8.0</version> </dependency>
二、application.yml
server: port: 8888 servlet: context-path: /server spring: application: name: springboot-manyDataSources datasource: p6spy: true dynamic: datasource: master: driver-class-name: com.p6spy.engine.spy.P6SpyDriver url: jdbc:p6spy:mysql://localhost:3306/datasourceName?characterEncoding=utf8&useSSL=false&serverTimezone=GMT username: root password: root # url: jdbc:mysql://localhost:3306/ datasourceName?characterEncoding=utf8&useSSL=false&serverTimezone=GMT # username: root # password: root # driver-class-name: com.mysql.cj.jdbc.Driver db2: driver-class-name: com.p6spy.engine.spy.P6SpyDriver url: jdbc:p6spy:sqlserver://localhost:1433;DatabaseName=datasourceName username: sa password: root # url: jdbc:sqlserver://localhost:1433;DatabaseName= datasourceName # username: sa # password: root # driver-class-name: com.microsoft.sqlserver.jdbc.SQLServerDriver #日志 logging: level: com.example.demo : debug
三、spy.properties
modulelist=com.baomidou.mybatisplus.extension.p6spy.MybatisPlusLogFactory,com.p6spy.engine.outage.P6OutageFactory
# 自定義日志打印
logMessageFormat=com.baomidou.mybatisplus.extension.p6spy.P6SpyLogger
#日志輸出到控制台
appender=com.baomidou.mybatisplus.extension.p6spy.StdoutLogger
# 使用日志系統記錄 sql
#appender=com.p6spy.engine.spy.appender.Slf4JLogger
# 設置 p6spy driver 代理
deregisterdrivers=true
# 取消JDBC URL前綴
useprefix=true
# 配置記錄 Log 例外,可去掉的結果集有error,info,batch,debug,statement,commit,rollback,result,resultset.
excludecategories=info,debug,result,commit,resultset
# 日期格式
dateformat=yyyy-MM-dd HH:mm:ss
# 實際驅動可多個
#driverlist=org.h2.Driver
# 是否開啟慢SQL記錄
outagedetection=true
# 慢SQL記錄標准 2 秒
outagedetectioninterval=2
四、MybatisPlusConfig
@Configuration @EnableTransactionManagement//開啟事務 public class MybatisPlusConfig { /** * mybatisplus 分頁插件 * @return */ @Bean public PaginationInterceptor paginationInterceptor(){ PaginationInterceptor paginationInterceptor = new PaginationInterceptor(); List<ISqlParser> sqlParserList = new ArrayList<>(); // 攻擊 SQL 阻斷解析器、加入解析鏈;防止小白或者惡意進行delete update 全表操作。注:若表配置使用了邏輯刪除將正常執行刪除。 sqlParserList.add(new BlockAttackSqlParser()); paginationInterceptor.setSqlParserList(sqlParserList); return paginationInterceptor; } /** *樂觀鎖插件:當要更新一條記錄的時候,希望這條記錄沒有被別人更新 * @return */ @Bean public OptimisticLockerInterceptor optimisticLockerInterceptor() { return new OptimisticLockerInterceptor(); } }
五、entity
5.1 ManageUser
@Data @Builder @Accessors(chain = true) @TableName("manage_user") @EqualsAndHashCode(callSuper = false) public class ManageUser extends Model<ManageUser> { private static final long serialVersionUID = 1L; /** * 管理員ID */ @TableId(value = "ID", type = IdType.AUTO) private Integer id; /** * 登陸名 */ @TableField("USERNAME") private String username; /** * 密碼 */ @TableField("PASSWORD") private String password; /** * 對應的角色Id */ @TableField("ROLE_ID") private Integer roleId; /** * 是否刪除 */ @TableField("IS_DEL") @TableLogic private Integer isDel = 0; @TableField("VERSION") @Version private Integer version; @Override protected Serializable pkVal() { return this.id; } }
5.2 VDepart
@Data @EqualsAndHashCode(callSuper = false) @Accessors(chain = true) @TableName("v_depart") public class VDepart extends Model<VDepart> { private static final long serialVersionUID = 1L; @TableId(value = "ID", type = IdType.AUTO) private Integer id; private String code; private String name; @Override protected Serializable pkVal() { return this.id; } }
六、controller
6.1 ManageUserController
@Slf4j @RestController @RequestMapping("/manageUser") @Transactional(rollbackFor=Exception.class) public class ManageUserController { @Autowired private ManageUserService manageUserService; @Autowired private JdbcTemplate jdbcTemplate; @GetMapping("/userList") public List<ManageUser> userList(){ return manageUserService.list(null); } //邏輯刪除 @GetMapping("/deleteUser") public boolean deleteUser(){ return manageUserService.removeById(4); } //jdbcTemplate @GetMapping("/deleteUserTrue/{userId}") public boolean deleteUserTrue(@PathVariable("userId") String userid){ boolean flag = false; int update = jdbcTemplate.update("DELETE FROM MANAGE_USER WHERE ID = ?;",userid); if(update>0){flag = true;} log.info("影響的行數:{} ", update); return flag; } //SQL 阻斷解析器 @GetMapping("/deleteUserAll") public boolean deleteUserAll(){ return manageUserService.remove(null); } //樂觀鎖 @GetMapping("/updateUser") public boolean updateUser(){ return manageUserService.updateUser(); } //事務 @GetMapping("/addUser") public boolean addUser(){ boolean root = manageUserService.save(ManageUser.builder().username("root").password("4ec847db9bc2bad60e4279cce1fad5db").roleId(1).build()); int i = 1/0; manageUserService.remove(null); return root; } }
6.2 VDepartController
@RestController @RequestMapping("/vDepart") public class VDepartController { @Autowired private VDepartService vDepartService; @GetMapping("/vDepartList") public List<VDepart> accountList(){ return vDepartService.list(); } @GetMapping("/vDepartPage/{page}/{limit}") public List<VDepart> vDepartPage(@PathVariable("page") int page, @PathVariable("limit") int limit){ IPage<VDepart> page1 = vDepartService.page(new Page<>(page, limit)); return page1.getRecords(); } }
七、 使用 @DS 切換數據源,不加@DS注解則默認master數據源
@DS 可以注解在方法上和類上,同時存在方法注解優先於類上注解。注解在service實現或mapper接口方法上,但強烈不建議同時在service和mapper注解。 (可能會有問題)
@DS("db2")
@Service
public class VDepartServiceImpl extends ServiceImpl<VDepartMapper, VDepart> implements VDepartService {
}
目錄結構:

釋:ManageUser為mysql數據庫用戶表,VDepart為sqlserver數據庫視圖
