【MybatisPlus】再補充內容
阿新 • • 發佈:2021-07-21
2021年7月21日 14點05分
看尚矽谷新講的尚醫通,這個MP的文件多了新東西:
依賴版本:
springBoot版本2.2.1.RELEASE
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency><!--mybatis-plus--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.3.1</version> </dependency> <!--mysql依賴--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!--lombok用來簡化實體類--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> </dependencies>
但是拉下來Spring報錯,死活找不到版本
我這裡乾脆換版本了:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd"> <modelVersion>4.0.0</modelVersion> <parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.3.0.RELEASE</version> <relativePath/> <!-- lookup parent from repository --> </parent> <groupId>com.atguigu</groupId> <artifactId>mybatis_plus</artifactId> <version>0.0.1-SNAPSHOT</version> <name>mybatis_plus</name> <description>Demo project for Spring Boot</description> <properties> <java.version>1.8</java.version> </properties> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <!--mybatis-plus--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.4.1</version> </dependency> <!--mysql依賴--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!--lombok用來簡化實體類--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> </dependencies> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>
一、自動填充
package com.atguigu.mybatis_plus.entity; import com.baomidou.mybatisplus.annotation.*; import lombok.Data; import java.util.Date; @Data public class User { @TableId(type = IdType.ASSIGN_ID) // 預設雪花演算法的主鍵策略 @TableId(type = IdType.AUTO) 自增策略 private Long id; private String name; private Integer age; private String email; // 自動填充註解? 需要實現 元物件處理器介面,自定義實現方法 @TableField(value = "createTime", fill = FieldFill.INSERT) private Date createTime; //create_time @TableField(value = "updateTime", fill = FieldFill.INSERT_UPDATE) private Date updateTime; }
元物件處理器介面實現:
package com.atguigu.mybatis_plus.handler; import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler; import org.apache.ibatis.reflection.MetaObject; import org.springframework.stereotype.Component; import java.util.Date; /** * 自動填充 * 需求描述: * 專案中經常會遇到一些資料,每次都使用相同的方式填充,例如記錄的建立時間,更新時間等。 * 我們可以使用MyBatis Plus的自動填充功能,完成這些欄位的賦值工作 * 1.1資料庫修改 * 在User表中新增datetime型別的新的欄位 create_time、update_time * * */ @Component public class CustomMetaObjectHandler implements MetaObjectHandler { @Override public void insertFill(MetaObject metaObject) { this.setFieldValByName("createTime",new Date(),metaObject); this.setFieldValByName("updateTime",new Date(),metaObject); this.setFieldValByName("recordVersion", 1, metaObject); } @Override public void updateFill(MetaObject metaObject) { this.setFieldValByName("updateTime",new Date(),metaObject); } }
二、樂觀鎖
專案裡面的持久層框架時ActiveJdbc,有這樣的應用場景,但是框架這塊沒提供相關的封裝
實現是人肉程式碼完成,程式邏輯有一點點封裝
MP這裡就配置一下就行了
package com.atguigu.mybatis_plus.entity; import com.baomidou.mybatisplus.annotation.*; import lombok.Data; import java.util.Date; @Data public class User { @TableId(type = IdType.ASSIGN_ID) // 預設雪花演算法的主鍵策略 @TableId(type = IdType.AUTO) 自增策略 private Long id; private String name; private Integer age; private String email; // 自動填充註解? 需要實現 元物件處理器介面,自定義實現方法 @TableField(value = "createTime", fill = FieldFill.INSERT) private Date createTime; //create_time @TableField(value = "updateTime", fill = FieldFill.INSERT_UPDATE) private Date updateTime; /** * 樂觀鎖 * 場景 * 主要適用場景:當要更新一條記錄的時候,希望這條記錄沒有被別人更新,也就是說實現執行緒安全的資料更新 * 樂觀鎖實現方式: * 取出記錄時,獲取當前version * 更新時,帶上這個version * 執行更新時, set version = newVersion where version = oldVersion * 如果version不對,就更新失敗 * 接下來介紹如何在Mybatis-Plus專案中,使用樂觀鎖: */ @Version @TableField(value = "recordVersion", fill = FieldFill.INSERT) // 設定預設值 private Integer recordVersion; @TableLogic private Integer deleted; // ALTER TABLE `user` ADD COLUMN `deleted` boolean DEFAULT false }
編寫配置類:
package com.atguigu.mybatis_plus.config; import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor; import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor; import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor; import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor; import org.mybatis.spring.annotation.MapperScan; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @Configuration @MapperScan("com.atguigu.mybatis_plus.mapper") public class MybatisPlusConfiguration { /** * 樂觀鎖外掛 已過時物件寫法 */ // @Bean // public OptimisticLockerInterceptor optimisticLockerInterceptor() { // return new OptimisticLockerInterceptor(); // } /** * 分頁外掛 * 已過時? */ // @Bean // public PaginationInterceptor paginationInterceptor() { // return new PaginationInterceptor(); // } @Bean public MybatisPlusInterceptor mybatisPlusInterceptor(){ // mp外掛介面 MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); // 新增樂觀鎖外掛 interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); // 新增分頁外掛 interceptor.addInnerInterceptor(new PaginationInnerInterceptor()); return interceptor; } }
樂觀鎖測試:
// 樂觀鎖案例 @Test void testingForOptimisticLocker() { // 首先插入一條記錄,檢查是否自動插入RecordVersion User user = new User(); user.setAge(24); user.setName("小紅"); user.setEmail("[email protected]"); int insert = userMapper.insert(user); // 然後使用ID查詢, 更改這條記錄, 檢查版本會不會更改為2 User user1 = userMapper.selectById(user.getId()); // 不確定這樣能否有效獲取ID, 建議從庫裡拿資料寫死 user1.setName("新小紅"); userMapper.updateById(user1); }
三、支援邏輯刪除
package com.atguigu.mybatis_plus.entity; import com.baomidou.mybatisplus.annotation.*; import lombok.Data; import java.util.Date; @Data public class User { @TableId(type = IdType.ASSIGN_ID) // 預設雪花演算法的主鍵策略 @TableId(type = IdType.AUTO) 自增策略 private Long id; private String name; private Integer age; private String email; // 自動填充註解? 需要實現 元物件處理器介面,自定義實現方法 @TableField(value = "createTime", fill = FieldFill.INSERT) private Date createTime; //create_time @TableField(value = "updateTime", fill = FieldFill.INSERT_UPDATE) private Date updateTime; /** * 樂觀鎖 * 場景 * 主要適用場景:當要更新一條記錄的時候,希望這條記錄沒有被別人更新,也就是說實現執行緒安全的資料更新 * 樂觀鎖實現方式: * 取出記錄時,獲取當前version * 更新時,帶上這個version * 執行更新時, set version = newVersion where version = oldVersion * 如果version不對,就更新失敗 * 接下來介紹如何在Mybatis-Plus專案中,使用樂觀鎖: */ @Version @TableField(value = "recordVersion", fill = FieldFill.INSERT) // 設定預設值 private Integer recordVersion; @TableLogic private Integer deleted; // ALTER TABLE `user` ADD COLUMN `deleted` boolean DEFAULT false }
配置檔案相關定義:
spring: datasource: url: jdbc:mysql://localhost:3308/atguigu-syt?serverTimezone=Asia/Shanghai driver-class-name: com.mysql.cj.jdbc.Driver username: root password: 123456 #mybatis日誌 mybatis-plus: global-config: db-config: id-type: auto #全域性設定主鍵生成策略 # 設定邏輯刪除值標準 (預設值) logic-delete-value: 1 logic-not-delete-value: 0 configuration: # 日誌輸出標準 log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
測試類的單元方法:
/** * 2、邏輯刪除 * 2.1物理刪除和邏輯刪除 * 物理刪除:真實刪除,將對應資料從資料庫中刪除,之後查詢不到此條被刪除資料 * 邏輯刪除:假刪除,將對應資料中代表是否被刪除欄位狀態修改為“被刪除狀態”,之後在資料庫中仍舊能看到此條資料記錄 * * 邏輯刪除的使用場景: * 可以進行資料恢復 * 有關聯資料,不便刪除 * * 2.2 邏輯刪除實現流程 * 2.2.1資料庫修改 * 新增 deleted欄位 * ALTERTABLE `user` ADD COLUMN `deleted` boolean DEFAULT false * * 2.2.2實體類修改 * 新增deleted 欄位,並加上 @TableLogic 註解 * @TableLogic * private Integer deleted; * * 2.2.3配置(可選) * application.properties 加入以下配置,此為預設值,如果你的預設值和mp預設的一樣,該配置可無 * mybatis-plus.global-config.db-config.logic-delete-value=1 * mybatis-plus.global-config.db-config.logic-not-delete-value=0 * * 2.2.4 測試 * 測試後發現,資料並沒有被刪除,deleted欄位的值由0變成了1 * 測試後分析列印的sql語句,是一條update * 注意:被刪除前,資料的deleted 欄位的值必須是 0,才能被選取出來執行邏輯刪除的操作 * @Test * public void testLogicDelete() { * int result = userMapper.deleteById(1L); * system.out.println(result); * } * * 2.2.5測試邏輯刪除後的查詢 * MyBatis Plus中查詢操作也會自動新增邏輯刪除欄位的判斷 * @Test * public void testLogicDeleteSelect() { * List<User> users = userMapper.selectList(null); * users.forEach(System.out::println); * } * * */ @Test public void testingForLogicDelete() { userMapper.deleteById(1); /** * ==> Preparing: UPDATE user SET deleted=1 WHERE id=? AND deleted=0 * ==> Parameters: 1(Integer) * <== Updates: 1 */ List<User> users = userMapper.selectList(null); /** * ==> Preparing: SELECT id,name,age,email,createTime,updateTime,recordVersion,deleted FROM user WHERE deleted=0 * ==> Parameters: * <== Columns: id, name, age, email, createTime, updateTime, recordVersion, deleted * <== Row: 2, Jack, 20, [email protected], null, null, null, 0 * <== Row: 3, Tom, 28, [email protected], null, null, null, 0 * <== Row: 4, Sandy, 21, [email protected], null, null, null, 0 * <== Row: 5, Billie, 24, [email protected], null, null, null, 0 * <== Row: 1417674045524021250, lucy, 20, [email protected], null, null, null, 0 * <== Row: 1417680764933292034, 王五AAA, 20, [email protected], 2021-07-21 11:00:08, 2021-07-21 11:01:07, 2, 0 * <== Total: 6 */ users.forEach(System.out::println); }