Mybatis-Plus進階分頁與樂觀鎖插件及通用枚舉和多數(shù)據(jù)源詳解
分頁插件
MP中自帶了分頁插件的功能,只需要在配置類中進行簡單的配置即可使用分頁的相關(guān)功能。分頁插件常常與前端的分頁顯示功能相關(guān),為了在前端美觀的顯示查詢到的數(shù)據(jù),通常會使用分頁插件,將所有的數(shù)據(jù)分成許多頁一頁一頁的進行顯示,不同頁的切換使用按鈕來完成
MP的插件配置類
@Configuration public class MybatisPlusConfiguration { @Bean public MybatisPlusInterceptor mybatisPlusInterceptor() { // 創(chuàng)建一個MybatisPlus的插件攔截器 MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor(); // 創(chuàng)建分頁的插件對象并設(shè)置數(shù)據(jù)庫類型 PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL); // 設(shè)置請求的頁面大于最大頁后操作, true調(diào)回到首頁,false 繼續(xù)請求 默認false paginationInnerInterceptor.setOverflow(true); // 設(shè)置分頁的單頁最多條數(shù),默認 500 條,-1 不受限制 paginationInnerInterceptor.setMaxLimit(500L); // 將這個分頁插件添加到攔截器中并返回 interceptor.addInnerInterceptor(paginationInnerInterceptor); return interceptor; } }
自定義方法并調(diào)用分頁
mapper定義方法
@Mapper @Repository public interface UserMapper extends BaseMapper<User> { /** * 通過年齡查詢用戶信息并分頁返回 * @param page 傳入一個page對象 * @param age 年齡 * @return 返回一個page對象 */ Page<User> selectPageVo(@Param("page") Page<User> page, @Param("age") Integer age); }
映射文件編寫SQL語句
<mapper namespace="com.xiaochen.mapper.UserMapper"> <select id="selectPageVo" resultType="com.xiaochen.domain.User"> select id,name,age,email from user where age > #{age} </select> </mapper>
測試方法調(diào)用自定義方法
@Autowired UserMapper mapper; @Test public void testpage() { // 創(chuàng)建一個page對象,設(shè)置當前頁是第1頁,每頁包含3條記錄 Page<User> page = new Page<>(2, 3); // mapper調(diào)用selectPage方法之后將結(jié)果返回給上面的page對象 // 第二個參數(shù)null的話就是查詢所有的記錄,如果有查詢條件的話就傳一個wrapper對象 mapper.selectPageVo(page, 20); // 當前頁的數(shù)據(jù) System.out.println(page.getRecords()); // 當前是第幾頁 System.out.println(page.getCurrent()); // 總頁數(shù) System.out.println(page.getPages()); // 每頁的記錄數(shù) System.out.println(page.getSize()); // 總記錄數(shù) System.out.println(page.getTotal()); // 是否有下一頁 System.out.println(page.hasNext()); // 是否有上一頁 System.out.println(page.hasPrevious()); }
樂觀鎖插件
要想使用樂觀鎖插件,首先要知道什么是樂觀鎖以及樂觀鎖出現(xiàn)的原因。現(xiàn)實生活中,一個管理系統(tǒng)往往不僅僅只有一個管理員,以修改商品價格為例,如果有兩個管理員小李和小王商品的原價為100,老板先是讓小李將商品的價格上調(diào)50,一段時間后讓小王將商品的價格下調(diào)20,由于小李有事耽擱,兩個人同時登錄管理系統(tǒng)獲取到商品的價格對其分別進行修改操作。如果小李最后完成操作的話商品最終為150元,如果小王最后完成操作的話商品最終為80元,這樣的話就會造成最終的價格不是老板想要的130。
要想使用代碼實現(xiàn)上述案例的話,使用線程來實現(xiàn)的話更加真實(可以模擬兩人處理先后的不確定性),但是為了簡化操作,設(shè)定最后完成操作的是小王,也即是說最后商品的價格為80
@Test public void happyLockTest() { // 小李查詢商品的價格 Product productLi = mapper.selectById(1); // 小王查詢到商品的價格 Product productWang = mapper.selectById(1); // +50 productLi.setPrice(productLi.getPrice() + 50); mapper.updateById(productLi); // -20 productWang.setPrice(productWang.getPrice() - 20); mapper.updateById(productWang); // 查詢最終的商品價格 System.out.println("最終價格為:" + mapper.selectById(1).getPrice()); }
// 控制臺最終打印 -> 最終價格為:80
有問題就有解決問題的方法,出現(xiàn)這個問題的原因就是兩個管理員同時獲取到了商品的信息并對他進行了修改,如果可以使用鎖限制同一時間只能有一個管理員對數(shù)據(jù)進行修改操作的話,就可以避免這個問題了,這就是悲觀鎖。
不對啊,不是說要講樂觀鎖的嘛怎么講到了悲觀鎖了?悲觀鎖將整張表鎖住了,阻止其他人對表進行修改操作,這樣的話對效率有很大的折損。于是樂觀鎖應(yīng)運而生,樂觀鎖允許任何人任何時候?qū)Ρ碇袛?shù)據(jù)進行修改,只不過數(shù)據(jù)表中要添加一個字段表示數(shù)據(jù)的當前版本號,數(shù)據(jù)每經(jīng)過一次更新版本號就相應(yīng)加一,數(shù)據(jù)每次更新的時候都會帶上版本號字段作為更新的條件。這樣的話就可以避免之前的問題了,兩人同時獲取到的版本都是0,小李修改之后就會將版本字段值加一也就是1,這時小王修改的時候就會查不到表中版本號為0的數(shù)據(jù)而無法修改。
這樣的話就會避免修改沖突,但是還是無法得到想要的結(jié)果,于是可以對兩人的修改結(jié)果進行判斷,如果更新操作的返回結(jié)果不是0的話就說明更新成功,否則就再次獲取數(shù)據(jù)表中的信息(這次就是為了獲得最新的版本號)再次進行更新操作
使用MP中的樂觀鎖插件,首先需要在配置類中將樂觀鎖插件添加到攔截器中,然后再在實體類中的版本號字段上使用@Version標志,然后就是和平常一樣的操作數(shù)據(jù)庫即可,執(zhí)行更新操作的時候會自動將當前查詢到的版本號當做條件拼接到SQL語句中
// 將樂觀鎖插件添加到攔截器中 interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor()); // 實體類標注版本號 @Version private Integer version; // 測試方法,測試兩個人最后的修改結(jié)果 @Test public void happyLockTest() { // 小李查詢商品的價格 Product productLi = mapper.selectById(1); // 小王查詢到商品的價格 Product productWang = mapper.selectById(1); // +50 int result = 0; do { // 更新失敗,重新查詢并修改 productLi = mapper.selectById(1); productLi.setPrice(productLi.getPrice() + 50); result = mapper.updateById(productLi); } while (result == 0); // -20 do { // 更新失敗,重新查詢并修改 productWang = mapper.selectById(1); productWang.setPrice(productWang.getPrice() - 20); result = mapper.updateById(productWang); } while (result == 0); // 查詢最終的商品價格 System.out.println("最終價格為:" + mapper.selectById(1).getPrice()); }
// 控制臺最終打印 -> 最終價格為:130
通用枚舉類
對于表中擁有固定幾個值的一些字段,可以使用枚舉類將比較簡單的數(shù)字或字符存入到數(shù)據(jù)庫表中,然后將這個簡單的數(shù)字或字符對應(yīng)著其具體的字符串表示,比如性別0代表女1代表男。這樣就會減輕數(shù)據(jù)庫的存儲壓力,提高用戶的使用體驗。 使用MP的通用枚舉必須先創(chuàng)建一個枚舉類,向外提供屬性的getter方法和全參構(gòu)造器,并使用@EnumValue注解將標識的屬性值在數(shù)據(jù)庫中存儲
@Getter @AllArgsConstructor public enum SexEnum { FEMALE(0, "女"), MALE(1, "男"); // 將注解標識的屬性值存儲到數(shù)據(jù)庫中 @EnumValue private Integer sex; private String sexName; }
然后實體類中修改字段對應(yīng)屬性的類型為枚舉類型,然后重寫toString方法,方便查詢結(jié)果顯示為數(shù)據(jù)表中數(shù)字或字符對應(yīng)的具體的字符串表示
// 修改字段對應(yīng)屬性的類型為枚舉類型 private SexEnum sex; // 重寫toString方法 @Override public String toString() { return "User{" + "id=" + id + ", name='" + name + '\'' + ", sex=" + sex.getSexName() + ", age=" + age + ", email='" + email + '\'' + ", isDeleted=" + isDeleted + '}'; }
最后在配置文件中設(shè)置通用枚舉的包,也就是相當于讓你寫的枚舉類生效
mybatis-plus: # 設(shè)置通用枚舉的包 type-enums-package: com.xiaochen.enums
測試
@Test public void enumTest() { User user = new User(); user.setName("張三"); user.setAge(23); user.setSex(SexEnum.FEMALE); mapper.insert(user); User user1 = mapper.selectById(6); System.out.println(user1); }
測試結(jié)果
多數(shù)據(jù)源
多數(shù)據(jù)源就是在一個程序中同時配置多個數(shù)據(jù)庫作為數(shù)據(jù)源進行操作,適用于多種場景:純粹多庫、 讀寫分離、 一主多從、 混合模式等。目前我們就來模擬一個純粹多庫的一個場景,配置兩個數(shù)據(jù)庫的兩張表,通過一個測試用例分別獲取兩張表的數(shù)據(jù),如果獲取到說明多庫模擬成功
第一步: 導(dǎo)入依賴
<!--mybatis-的場景啟動器--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.5.1</version> </dependency>
第二步: 配置文件配置多數(shù)據(jù)源
spring:
# 配置數(shù)據(jù)源信息
datasource:
dynamic:
# 設(shè)置默認的數(shù)據(jù)源或者數(shù)據(jù)源組,當設(shè)置的數(shù)據(jù)源都找不到時使用默認數(shù)據(jù)源,默認值即為master
primary: master
# 嚴格匹配數(shù)據(jù)源,默認false.true未匹配到指定數(shù)據(jù)源時拋異常,false匹配不到指定數(shù)據(jù)源時使用默認數(shù)據(jù)源
strict: false
datasource:
# 主數(shù)據(jù)源
master:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/mybatis_plus
username: root
password: 123456
# 從數(shù)據(jù)源
slave_1:
driver-class-name: com.mysql.jdbc.Driver
url: jdbc:mysql://localhost:3306/test
username: root
password: 123456
第三步: 照常使用方法測試在兩個數(shù)據(jù)庫查詢兩張表,唯一不同的就是在service的實現(xiàn)類上使用@DS注解,標注service實現(xiàn)類的所有方法都是對指定數(shù)據(jù)源進行操作的
測試類及結(jié)果
到此這篇關(guān)于Mybatis-Plus進階分頁與樂觀鎖插件及通用枚舉和多數(shù)據(jù)源詳解的文章就介紹到這了,更多相關(guān)Mybatis-Plus 分頁插件內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java生成訂單號或唯一id的高并發(fā)方案(4種方法)
本文主要介紹了Java生成訂單號或唯一id的高并發(fā)方案,包括4種方法,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧2024-01-01java中將科學(xué)計數(shù)法轉(zhuǎn)換普通計數(shù)法的簡單方法
下面小編就為大家?guī)硪黄猨ava中將科學(xué)計數(shù)法轉(zhuǎn)換普通計數(shù)法的簡單方法。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2016-12-12Spring?Boot?使用?SSE?方式向前端推送數(shù)據(jù)詳解
這篇文章主要介紹了Spring?Boot?使用SSE方式向前端推送數(shù)據(jù)詳解,SSE簡單的來說就是服務(wù)器主動向前端推送數(shù)據(jù)的一種技術(shù),它是單向的,也就是說前端是不能向服務(wù)器發(fā)送數(shù)據(jù)的2022-08-08Java KindEditor粘貼圖片自動上傳到服務(wù)器功能實現(xiàn)
這篇文章主要介紹了Java KindEditor粘貼圖片自動上傳到服務(wù)器功能實現(xiàn),本文給大家介紹的非常詳細,對大家的學(xué)習(xí)或工作具有一定的參考借鑒價值,需要的朋友可以參考下2023-04-04Spring?Boot?整合?Fisco?Bcos部署、調(diào)用區(qū)塊鏈合約的案例
本篇文章介紹?Spring?Boot?整合?Fisco?Bcos?的相關(guān)技術(shù),最最重要的技術(shù)點,部署、調(diào)用區(qū)塊鏈合約的工程案例,本文通過流程分析給大家介紹的非常詳細,需要的朋友參考下吧2022-01-01