MyBatis-Plus(Ⅵ)插件

目錄

一、分頁插件

1.添加配置類

2.在測試類測試

結果

二、xml實現分頁的自定義

1.UserMapper中定義接口方法

2.創建UserMapper.xml文件

?3.在測試類測試

結果

?三、樂觀鎖

1.場景

2.樂觀鎖與悲觀鎖

?3.模擬修改沖突

數據庫中添加商品表

添加數據

添加實體類

添加mapper

測試

結果

?樂觀鎖實現流程

4.Mybatis-Plus實現樂觀鎖

首先修改實體類

?添加樂觀鎖插件配置

測試?

結果


一、分頁插件

MyBatis?Plus自帶分頁插件,只要簡單的配置即可實現分頁功能。

1.添加配置類

package com.example.mybatisplus.config;import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;/*** 此配置類的作用是向 Spring 容器注冊一個 MybatisPlusInterceptor 攔截器,* 該攔截器會在執行 SQL 時攔截分頁查詢語句,* 并自動處理分頁邏輯,包含計算總記錄數、總頁數等。* */
@Configuration
public class MyBatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));return interceptor;}
}

2.在測試類測試

package com.example.mybatisplus;import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.mybatisplus.entity.User;
import com.example.mybatisplus.mapper.UserMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;import java.util.*;@SpringBootTest
public class Test4{@AutowiredUserMapper userMapper;@Testpublic void testPage(){//設置分頁參數Page<User> page = new Page<>(1, 5);userMapper.selectPage(page, null);//獲取分頁數據List<User> list = page.getRecords();list.forEach(System.out::println);System.out.println("當前頁:"+page.getCurrent());System.out.println("每頁顯示的條數:"+page.getSize());System.out.println("總記錄數:"+page.getTotal());System.out.println("總頁數:"+page.getPages());System.out.println("是否有上一頁:"+page.hasPrevious());System.out.println("是否有下一頁:"+page.hasNext());}
}
結果

二、xml實現分頁的自定義

1.UserMapper中定義接口方法

/*** 根據年齡查詢用戶列表,分頁顯示* @param page 分頁對象 ,xml中可以從里面進行取值 ,傳遞參數 Page 即自動分頁 ,必須放在第一位* @param age 年齡* @return */Page<User> selectPageVo(@Param("page") Page<User> page, @Param("age") Integer age);

?即:

2.創建UserMapper.xml文件

在這里面能配置分頁的條件:

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd"><mapper namespace="com.example.mybatisplus.mapper.UserMapper"><!--SQL片段,記錄基礎字段--><sql id="BaseColumns">id,name,age,email</sql><!--IPage<User> selectPageVo(Page<User> page, Integer age);--><select id="selectPageVo" resultType="com.example.mybatisplus.entity.User">SELECT <include refid="BaseColumns"></include> FROM t_user WHERE age > #{age}</select></mapper>

?3.在測試類測試

  @Testpublic void testSelectPageVo(){//設置分頁參數Page<User> page = new Page<>(1, 5);userMapper.selectPageVo(page, 20);//獲取分頁數據List<User> list = page.getRecords();list.forEach(System.out::println);System.out.println("當前頁:"+page.getCurrent());System.out.println("每頁顯示的條數:"+page.getSize());System.out.println("總記錄數:"+page.getTotal());System.out.println("總頁數:"+page.getPages());System.out.println("是否有上一頁:"+page.hasPrevious());System.out.println("是否有下一頁:"+page.hasNext());}
結果

因為加了age的限制,所以這里查詢出來去分頁的數據就變少了

?三、樂觀鎖

1.場景

一件商品,成本價是80元,售價是100元。老板先是通知小李,說你去把商品價格增加50元。小?李正在玩游戲,耽擱了一個小時。正好一個小時后,老板覺得商品價格增加到150元,價格太

高,可能會影響銷量。又通知小王,你把商品價格降低30元。

此時,小李和小王同時操作商品后臺系統。小李操作的時候,系統先取出商品價格100元;小王??也在操作,取出的商品價格也是100元。小李將價格加了50元,并將100+50=150元存入了數據 ?庫;小王將商品減了30元,并將100-30=70元存入了數據庫。是的,如果沒有鎖,小李的操作就?完全被小王的覆蓋了。

那么現在商品價格是70元,比成本價低10元。幾分鐘后,這個商品很快出售了1千多件商品,老板虧1?萬多。

2.樂觀鎖與悲觀鎖

上面的故事,如果是樂觀鎖,小王保存價格前,會檢查下價格是否被人修改過了。如果被修改過了,則重新取出的被修改后的價格,150元,這樣他會將120元存入數據庫。

如果是悲觀鎖,小李取出數據后,小王只能等小李操作完之后,才能對價格進行操作,也會保證最終的價格是120元。

特性悲觀鎖樂觀鎖
鎖定時機讀取數據時鎖定更新數據時檢查
沖突預防通過鎖定數據來預防沖突通過檢測數據變更來處理沖突
性能通常性能較低,因為涉及到鎖的獲取和釋放通常性能較高,因為沒有鎖的開銷
適用場景高沖突環境,寫操作頻繁低沖突環境,讀操作頻繁
實現方式數據庫鎖機制,如行鎖、表鎖版本號或時間戳等機制
用戶體驗用戶可能感知到鎖的存在,如長時間等待用戶通常感知不到鎖的存在
數據一致性強一致性保證最終一致性,依賴于沖突檢測和處理

?3.模擬修改沖突

數據庫中添加商品表

CREATE TABLE t_product
(
id BIGINT(20) NOT NULL COMMENT '主鍵ID',
NAME VARCHAR(30) NULL DEFAULT NULL COMMENT '商品名稱 ',
price INT(11) DEFAULT 0 COMMENT '價格 ',
VERSION INT(11) DEFAULT 0 COMMENT '樂觀鎖版本號 ',
PRIMARY KEY (id)
);

添加數據

INSERT INTO t_product (id, NAME, price) VALUES (1, '外星人筆記本 ', 100);

添加實體類

package com.example.mybatisplus.entity;import lombok.*;@Data //lombok注解
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@ToString
public class Product {private Long id;private String name;private Integer price;private Integer version;
}

添加mapper

package com.example.mybatisplus.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.example.mybatisplus.entity.Product;@Repository
public interface ProductMapper extends BaseMapper<Product> {}

測試

package com.example.mybatisplus;import com.example.mybatisplus.entity.Product;
import com.example.mybatisplus.mapper.ProductMapper;
import org.junit.jupiter.api.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;@SpringBootTest
public class Test5 {@AutowiredProductMapper productMapper;@Testpublic void testConcurrentUpdate() {//1、小李Product p1 = productMapper.selectById(1L);System.out.println("小李取出的價格:" + p1.getPrice());//2、小王Product p2 = productMapper.selectById(1L);System.out.println("小王取出的價格:" + p2.getPrice());//3、小李將價格加了50元,存入了數據庫p1.setPrice(p1.getPrice() + 50);int result1 = productMapper.updateById(p1);System.out.println("小李修改結果:" + result1);//4、小王將商品減了30元,存入了數據庫p2.setPrice(p2.getPrice() - 30);int result2 = productMapper.updateById(p2);System.out.println("小王修改結果:" + result2);//最后的結果Product p3 = productMapper.selectById(1L);//價格覆蓋,最后的結果:70System.out.println("最后的結果:" + p3.getPrice());}}
結果

這里為了查看方便,我先將配置文件中的日志關閉了。

關一下日志

可以清晰看出變化結果:?

沒有鎖的情況下

?樂觀鎖實現流程

數據庫中添加version字段(當然這個咱們在創建時已經創了)

取出記錄時,獲取當前version

SELECT?id,`name`,price,`version` FROM?product?WHERE?id=1

更新時,?version?+?1,如果where語句中的version版本不對,則更新失敗

UPDATE?product?SET?price=price+50,?`version`=`version` +?1?WHERE?id=1 AND `version`=1

4.Mybatis-Plus實現樂觀鎖

首先修改實體類

為version字段添加@Version注解

?添加樂觀鎖插件配置

在方才的分頁配置這里加一條:

//添加樂觀鎖插件
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
不用令寫,加一條就行

測試?

當然在測試之前,先將數據調回100:

然后再進行測試:?

/***樂觀鎖版本* */@Testpublic void testConcurrentVersionUpdate() {//小李取數據Product p1 = productMapper.selectById(1L);//小王取數據Product p2 = productMapper.selectById(1L);//小李修改 + 50p1.setPrice(p1.getPrice() + 50);int result1 = productMapper.updateById(p1);System.out.println("小李修改的結果:" + result1);//小王修改 - 30p2.setPrice(p2.getPrice() - 30);int result2 = productMapper.updateById(p2);System.out.println("小王修改的結果:" + result2);if(result2 == 0){//失敗重試,重新獲取version并更新p2 = productMapper.selectById(1L);p2.setPrice(p2.getPrice() - 30);result2 = productMapper.updateById(p2);}System.out.println("小王修改重試的結果:" + result2);//老板看價格Product p3 = productMapper.selectById(1L);System.out.println("老板看價格:" + p3.getPrice());}
結果
達成了預想結果

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/diannao/75761.shtml
繁體地址,請注明出處:http://hk.pswp.cn/diannao/75761.shtml
英文地址,請注明出處:http://en.pswp.cn/diannao/75761.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

火山引擎云上實戰: DeepSeek R1 大模型(全尺寸)

本文將介紹兩種在火山引擎云上部署 DeepSeek-R1 全尺寸模型服務的方案&#xff0c;涵蓋大模型推理服務的 Terraform 一鍵部署、容器化部署、資源彈性伸縮和模型可觀測。 來源 | 火山引擎云基礎 在 AI 大模型日新月異的當下&#xff0c;企業在使用大模型時往往面臨著數據隱私保…

vue遺漏的知識點(動態組件.)

----動態組件&#xff08;vue2vue3通用&#xff09; <component :is"..."> 的作用 <component> 是 Vue 的內置組件&#xff0c;用于動態渲染其他組件。:is 屬性 用于指定要渲染的組件。它的值可以是&#xff1a; 組件的名稱&#xff08;字符串&#xf…

工作流引擎Flowable介紹及SpringBoot整合使用實例

Flowable簡介 Flowable 是一個輕量級的業務流程管理&#xff08;BPM&#xff09;和工作流引擎&#xff0c;基于 Activiti 項目發展而來&#xff0c;專注于提供高性能、可擴展的工作流解決方案。它主要用于企業級應用中的流程自動化、任務管理和審批流等場景。 Flowable 的核心…

【uni-app】引用公共組件

目錄 一、建立公共組件 1.1新建vue文件 1.2編寫公共文件代碼 1.3使用 注意事項 一、建立公共組件 1.1新建vue文件 在公共組件文件目錄下新建所需要的功能文件 1.2編寫公共文件代碼 按需求寫對應功能的代碼 1.3使用 在需要使用的文件下引用公共組件 注意事項 想要使用s…

STL中vector模擬實現

vector各個接口函數 //構造函數 vector() vector(size_t n,const T& valT()) vector(int n,const T& val T()) //拷貝構造函數 vector(const vector<T>& v) //迭代器版本的 vector(inputiterator first, inputiterator end) //賦值運算符重載 vector<T&…

DML 數據操縱語言學習筆記

一、DML 核心概念體系 1.1 語言定位與邊界 DML&#xff08;Data Manipulation Language&#xff09;作為 SQL 三大核心語言之一&#xff0c;專注于數據行級操作&#xff0c;區別于 DDL&#xff08;結構定義&#xff09;和 DCL&#xff08;權限控制&#xff09;。其核心指令包…

springboot的跨域是什么?遇到跨域問題如何解決?

在Spring Boot中&#xff0c;跨域是指當瀏覽器中的前端應用&#xff08;如運行在某個域名和端口下的前端頁面&#xff09;請求后端接口時&#xff0c;如果后端接口所在的域名、端口或協議與前端應用不一致&#xff0c;瀏覽器會阻止這種跨域請求。這是由于瀏覽器的同源策略&…

嘯叫抑制(AFS)從算法仿真到工程源碼實現-第八節-系統搭建

一、概述 系統分為錄音模塊、數據處理模塊、播音模塊。錄音模塊和播音模塊使用alsa庫進行讀寫數據。各模塊為獨立進程處理&#xff0c;模塊之間使用命名管道進行數據的傳輸。數據處理模塊我們使用基于頻域的自適應濾波去嘯叫算法。 二、工程實現 2.1 系統流程圖 2.2 錄音模塊…

HTML——什么是塊級元素,什么是內聯元素,有何區別

在 HTML 中&#xff0c;塊級元素&#xff08;Block-level element&#xff09;和內聯元素&#xff08;Inline element&#xff09;是兩種不同類型元素&#xff0c;它們在頁面布局和樣式應用方面有不同的行為和特性。 塊級元素&#xff08;Block-level element&#xff09; 塊級…

01 設計模式和設計原則

類設計原則&#xff1a; 單一職責原則&#xff08;Single Responsibility Principle&#xff0c;SRP&#xff09;&#xff1a;實現類要職責單一開閉原則&#xff08;Open Close Principle&#xff0c;OCP&#xff09;&#xff1a;對擴展開放&#xff0c;對修改關閉里氏替換原則…

【踩坑日記】springboot 打包后實現類無法找到

試過了所有改什么目錄 依賴 clean都以失敗告終 最后將實現類的文件名從Impl改成impl宣布成功 記得使用idea自帶的重構

項目-蒼穹外賣(十五) WebSocket+語音播報功能實現(來訂單+催單)

一、介紹 二、入門案例 配置類&#xff1a; package com.sky.config;import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.web.socket.server.standard.ServerEndpointExporter;/…

【Spring篇】Spring的生命周期

一、Bean 生命周期的核心階段 1. 實例化&#xff08;Instantiation&#xff09; ? 觸發時機&#xff1a;容器啟動時&#xff08;單例 Bean&#xff09;或請求時&#xff08;原型 Bean&#xff09;。 ? 實現方式&#xff1a; 通過反射&#xff08;Class.newInstance() 或構造…

Redis、Memcached應用場景對比

環境 Redis官方網站&#xff1a; Redis - The Real-time Data Platform Redis社區版本下載地址&#xff1a;Install Redis | Docs Memcached官方網站&#xff1a;memcached - a distributed memory object caching system Memcached下載地址&#xff1a;memcached - a dis…

kettle插件-mysql8數據庫插件

場景&#xff1a;群里有小伙伴反饋kettle 7.x版本不能自動連接mysql8&#xff0c;安排&#xff01;&#xff01;&#xff01; 1、將mysql8的驅動包mysql-connector-java-8.0.20.jar丟到kettle的lib目錄下&#xff0c;重啟spoon。 2、配置數據庫連接&#xff0c;提示驅動類不對…

【軟件測試】:軟件測試實戰

1. ?動化實施步驟 1.1 編寫web測試?例 1.2 ?動化測試腳本開發 common public class AutotestUtils {public static EdgeDriver driver;// 創建驅動對象public static EdgeDriver createDriver(){// 驅動對象已經創建好了 / 沒有創建if( driver null){driver new EdgeDr…

深度學習入門1 基于Python的理論與實現

torch.unsqueeze()將一維數據變為二維數據&#xff0c;torch只能處理二維數據 tensor不能反向&#xff0c;variable可以反向。variable.data.numpy()轉換為numpy 第3章 神經網絡 實現softmax函數時的注意事項&#xff1a;為防止e的指數運算造成溢出 矩陣的第 0 維是列方向,第…

解決 Pentaho Kettle 插件集成中的 NoSuchMethodError: ContextFactory.enterContext() 錯誤

解決 Pentaho Kettle 插件集成中的 NoSuchMethodError: ContextFactory.enterContext() 錯誤 在使用 Pentaho Data Integration&#xff08;也稱為 Kettle&#xff09;進行數據集成和ETL開發時&#xff0c;開發者可能會遇到各種依賴沖突和技術挑戰。本文將詳細介紹一個常見的錯…

第 五 章:優化算法_《C++性能優化指南》_notes

優化算法 第五章重難點詳解與代碼實戰編譯與測試說明第五章核心知識點整理重難點梳理 第一部分&#xff1a;多選題&#xff08;10道&#xff09;第二部分&#xff1a;設計題&#xff08;5道&#xff09;答案與詳解多選題答案&#xff1a; 設計題參考實現&#xff08;以題目2為例…

多版本PHP開發環境配置教程:WAMPServer下MySQL/Apache/MariaDB版本安裝與切換

提示&#xff1a;文章寫完后&#xff0c;目錄可以自動生成&#xff0c;如何生成可參考右邊的幫助文檔 文章目錄 前言一、版本切換指南總結 前言 由于有幾個項目分別使用到PHP7.0 和7.4以及8.0版本&#xff0c;設置mysql也會根據PHP版本使用不同的版本&#xff0c;于是開始研究…