MyBatis-Plus 乐观锁 防止超卖、逻辑删除、自动填充、Id自增
MyBatis-Plus 樂觀鎖 防止超賣、邏輯刪除、自動填充 Day3
前面的簡單的講了一下mybatis-plus的使用 當然有很多不足 我寫博客就是想促進大家一起學習 也想讓這些內容更簡單一些。
介紹
這次就主要講樂觀鎖、邏輯刪除、自動填充。這幾項在項目是用的非常多的。
先講一下主要應用 之后再講理論和實現。
樂觀鎖:
主要用于防止商品超賣的方面
邏輯刪除:
邏輯刪除主要是用于用戶對于數據的誤刪的一種撤銷機制。
刪除分為兩種
- 一種是物理刪除 就是數據庫層面的刪除 徹底的從磁盤中刪除
- 另外一種就是今天講的 邏輯刪除 刪除后還是會在數據庫里保存著 只是查詢的時候 需要帶上參數才能查到
- 當然徹底刪除的時候也是需要帶上那個參數才能徹底刪除的。
自動填充:
-
我之前看阿里的那個規范的時候 有看到就是說在數據庫里面建立每一張表 都需要有創建時間和修改時間
-
所以MP就提供自動填充的功能,幫助自定設置這些字段的值,提升開發效率,代碼也會顯得特別優雅。
樂觀鎖
當要更新一條記錄的時候,希望這條記錄沒有被別人更新
樂觀鎖實現方式:
- 取出記錄時,獲取當前version
- 更新時,帶上這個version
- 執行更新時, set version = newVersion where version = oldVersion
- 如果version不對,就更新失敗
能夠保證數據的安全性和一致性。
因為后面還有邏輯刪除、自動填充 環境就全部搭好拉。
使用方法
字段上加上@Version注解
@Version private Integer version;mybatis配置注入下面這個bean
@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());return mybatisPlusInterceptor;}環境搭建 :
-
表
DROP TABLE IF EXISTS `user`; CREATE TABLE `user` (`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主鍵ID',`name` varchar(30) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '姓名',`age` int(11) NULL DEFAULT NULL COMMENT '年齡',`email` varchar(50) CHARACTER SET utf8 COLLATE utf8_general_ci NULL DEFAULT NULL COMMENT '郵箱',`version` int(10) NULL DEFAULT 1 COMMENT '樂觀鎖',`deleted` int(10) NULL DEFAULT 0 COMMENT '邏輯刪除',`create_time` datetime(0) NULL DEFAULT NULL COMMENT '創建時間',`update_time` datetime(0) NULL DEFAULT NULL COMMENT '更新時間',PRIMARY KEY (`id`) USING BTREE ) ENGINE = InnoDB AUTO_INCREMENT = 1337575143814062086 CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic; -
要導入的依賴 這里就不說了 我之前的博客也有。
-
user層
@Data @AllArgsConstructor @NoArgsConstructor @Accessors(chain = true) @TableName(value = "user") public class User {@TableId(type = IdType.AUTO)private Long id;private String name;private Integer age;private String email;@Version // 這里是樂觀鎖的注解private Integer version;@TableLogic // 這是邏輯刪除的注解private Integer deleted;@TableField(fill = FieldFill.INSERT) //這里是自動填充的注解private Date createTime;@TableField(fill = FieldFill.INSERT_UPDATE)private Date updateTime; } -
mapper層
public interface UserMapper extends BaseMapper<User> {} -
MyBatisPlusConfig
@Configuration public class MybatisPlusConfig {// 分頁@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor mybatisPlusInterceptor = new MybatisPlusInterceptor();// 這里是注冊分頁插件mybatisPlusInterceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));// 注冊樂觀鎖 插件mybatisPlusInterceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());return mybatisPlusInterceptor;} } -
yaml
server:port: 8484 spring:datasource:driver-class-name: com.mysql.cj.jdbc.Driverusername: rootpassword: 123456url: jdbc:mysql://localhost:3306/mybatis_plus?serverTimezone=UTC&useSSL=false&characterEncoding=utf8&serverTimezone=GMT
樂觀鎖測試
先測試一下 沒有加樂觀鎖的 會是什么樣
@Testpublic void updateOptimisticLockerInterceptor(){//A 線程User user = userMapper.selectById(102L);user.setName("點贊1");user.setAge(3);//B 線程 模擬另外一個線程插隊User user1 = userMapper.selectById(102L);user1.setName("收藏加三連");user1.setAge(4);userMapper.updateById(user1);// 自旋鎖來嘗試多次提交userMapper.updateById(user); // 如果沒有樂觀鎖 就會覆蓋插隊的值}下面給大家看一下控制臺的輸出
為了方便觀看 我把測試數據改了 來接著看一下這次的結果
@Testpublic void updateOptimisticLockerInterceptor(){//A 線程User user = userMapper.selectById(102L);user.setName("關注寧在春");user.setAge(3);//B 線程 模擬另外一個線程插隊User user1 = userMapper.selectById(102L);user1.setName("給寧在春點贊");user1.setAge(4);userMapper.updateById(user1);// 自旋鎖來嘗試多次提交userMapper.updateById(user); // 如果沒有樂觀鎖 就會覆蓋插隊的值}這就是加了樂觀鎖的作用 在多線程下 可以保證數據的安全 防止商品超賣等等。
邏輯刪除
只對自動注入的sql起效:
- 插入: 不作限制
- 查找: 追加where條件過濾掉已刪除數據,且使用 wrapper.entity 生成的where條件會忽略該字段
- 更新: 追加where條件防止更新到已刪除數據,且使用 wrapper.entity 生成的where條件會忽略該字段
- 刪除: 轉變為 更新
例如:
- 刪除: update user set deleted=1 where id = 1 and deleted=0
- 查找: select id,name,deleted from user where deleted=0
使用方法:
步驟1: 配置
- 在application.yml 加入下面配置
步驟2: 實體類字段上加上@TableLogic注解
@TableLogic private Integer deleted;邏輯刪除 測試
// TODO tableLogic 邏輯刪除 @Test public void tableLogic(){userMapper.deleteById(103);List<User> userList = userMapper.selectList(null);userList.forEach(System.out::println); }測試結果如下 使用查詢全部方法 明顯查不到這行數據拉 我們接下來看看 數據庫里的表 看還有沒有
數據庫里面還存在 只是deleted 變成1拉
自動填充
原理:
- 實現元對象處理器接口:com.baomidou.mybatisplus.core.handlers.MetaObjectHandler
- 注解填充字段 @TableField(.. fill = FieldFill.INSERT) 生成器策略部分也可以配置!
-
自定義實現類 MyMetaObjectHandler
@Slf4j @Component public class MyMetaObjectHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {log.info("start insert fill ....");this.setFieldValByName("createTime",new Date(),metaObject);this.setFieldValByName("updateTime",new Date(),metaObject);}@Overridepublic void updateFill(MetaObject metaObject) {log.info("start update fill ....");this.setFieldValByName("updateTime",new Date(),metaObject);} }
測試
我們來增加一行數據看一看會不會吧 這里把Id 自增也講一起講了吧
mybatisplus 默認的主鍵自增 是默認使用雪花算法+UUID(不含中劃線)
具體的 大家可以自行研究。
//TODO insert 配置了自動填充后的insert @Test public void insert() {User user = new User().setName("自動填充").setAge(99).setEmail("ssss@qq.com");int i = userMapper.insert(user);System.out.println(i);Map<String, Object> map = new HashMap<String,Object>();map.put("name","自動填充");List<User> users = userMapper.selectByMap(map);users.forEach(System.out::println); }測試圖:
搞定
溜了溜了
大家看的好 就評論評論 一起學習學習咯
剛開始 文筆不咋好 爭取之后 我加油寫的好一些 再來點故事。
總結
以上是生活随笔為你收集整理的MyBatis-Plus 乐观锁 防止超卖、逻辑删除、自动填充、Id自增的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: MyBatis-Plus Day2 Wa
- 下一篇: RBAC、控制权限设计、权限表设计 基于