溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

Mybatis-Plus進(jìn)階分頁(yè),樂(lè)觀鎖插件,通用枚舉和多數(shù)據(jù)源實(shí)例分析

發(fā)布時(shí)間:2022-03-22 09:05:18 來(lái)源:億速云 閱讀:140 作者:iii 欄目:開發(fā)技術(shù)

這篇文章主要介紹了Mybatis-Plus進(jìn)階分頁(yè),樂(lè)觀鎖插件,通用枚舉和多數(shù)據(jù)源實(shí)例分析的相關(guān)知識(shí),內(nèi)容詳細(xì)易懂,操作簡(jiǎn)單快捷,具有一定借鑒價(jià)值,相信大家閱讀完這篇Mybatis-Plus進(jìn)階分頁(yè),樂(lè)觀鎖插件,通用枚舉和多數(shù)據(jù)源實(shí)例分析文章都會(huì)有所收獲,下面我們一起來(lái)看看吧。

分頁(yè)插件

??MP中自帶了分頁(yè)插件的功能,只需要在配置類中進(jìn)行簡(jiǎn)單的配置即可使用分頁(yè)的相關(guān)功能。分頁(yè)插件常常與前端的分頁(yè)顯示功能相關(guān),為了在前端美觀的顯示查詢到的數(shù)據(jù),通常會(huì)使用分頁(yè)插件,將所有的數(shù)據(jù)分成許多頁(yè)一頁(yè)一頁(yè)的進(jìn)行顯示,不同頁(yè)的切換使用按鈕來(lái)完成 MP的插件配置類

@Configuration
public class MybatisPlusConfiguration {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        // 創(chuàng)建一個(gè)MybatisPlus的插件攔截器
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();

        // 創(chuàng)建分頁(yè)的插件對(duì)象并設(shè)置數(shù)據(jù)庫(kù)類型
        PaginationInnerInterceptor paginationInnerInterceptor = new PaginationInnerInterceptor(DbType.MYSQL);
        // 設(shè)置請(qǐng)求的頁(yè)面大于最大頁(yè)后操作, true調(diào)回到首頁(yè),false 繼續(xù)請(qǐng)求  默認(rèn)false
        paginationInnerInterceptor.setOverflow(true);
        // 設(shè)置分頁(yè)的單頁(yè)最多條數(shù),默認(rèn) 500 條,-1 不受限制
        paginationInnerInterceptor.setMaxLimit(500L);

        // 將這個(gè)分頁(yè)插件添加到攔截器中并返回
        interceptor.addInnerInterceptor(paginationInnerInterceptor);
        return interceptor;
    }
}

自定義方法并調(diào)用分頁(yè) mapper定義方法

@Mapper
@Repository
public interface UserMapper extends BaseMapper<User> {

    /**
     * 通過(guò)年齡查詢用戶信息并分頁(yè)返回
     * @param page 傳入一個(gè)page對(duì)象
     * @param age  年齡
     * @return 返回一個(gè)page對(duì)象
     */
    Page<User> selectPageVo(@Param("page") Page<User> page, @Param("age") Integer age);
}

映射文件編寫SQL語(yǔ)句

<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>

測(cè)試方法調(diào)用自定義方法

@Autowired
UserMapper mapper;

@Test
public void testpage() {

    // 創(chuàng)建一個(gè)page對(duì)象,設(shè)置當(dāng)前頁(yè)是第1頁(yè),每頁(yè)包含3條記錄
    Page<User> page = new Page<>(2, 3);

    // mapper調(diào)用selectPage方法之后將結(jié)果返回給上面的page對(duì)象
    // 第二個(gè)參數(shù)null的話就是查詢所有的記錄,如果有查詢條件的話就傳一個(gè)wrapper對(duì)象
   mapper.selectPageVo(page, 20);

    // 當(dāng)前頁(yè)的數(shù)據(jù)
    System.out.println(page.getRecords());
    // 當(dāng)前是第幾頁(yè)
    System.out.println(page.getCurrent());
    // 總頁(yè)數(shù)
    System.out.println(page.getPages());
    // 每頁(yè)的記錄數(shù)
    System.out.println(page.getSize());
    // 總記錄數(shù)
    System.out.println(page.getTotal());
    // 是否有下一頁(yè)
    System.out.println(page.hasNext());
    // 是否有上一頁(yè)
    System.out.println(page.hasPrevious());
}

樂(lè)觀鎖插件

??要想使用樂(lè)觀鎖插件,首先要知道什么是樂(lè)觀鎖以及樂(lè)觀鎖出現(xiàn)的原因。現(xiàn)實(shí)生活中,一個(gè)管理系統(tǒng)往往不僅僅只有一個(gè)管理員,以修改商品價(jià)格為例,如果有兩個(gè)管理員小李和小王商品的原價(jià)為100,老板先是讓小李將商品的價(jià)格上調(diào)50,一段時(shí)間后讓小王將商品的價(jià)格下調(diào)20,由于小李有事耽擱,兩個(gè)人同時(shí)登錄管理系統(tǒng)獲取到商品的價(jià)格對(duì)其分別進(jìn)行修改操作。如果小李最后完成操作的話商品最終為150元,如果小王最后完成操作的話商品最終為80元,這樣的話就會(huì)造成最終的價(jià)格不是老板想要的130。 要想使用代碼實(shí)現(xiàn)上述案例的話,使用線程來(lái)實(shí)現(xiàn)的話更加真實(shí)(可以模擬兩人處理先后的不確定性),但是為了簡(jiǎn)化操作,設(shè)定最后完成操作的是小王,也即是說(shuō)最后商品的價(jià)格為80

@Test
public void happyLockTest() {
    // 小李查詢商品的價(jià)格
    Product productLi = mapper.selectById(1);
    // 小王查詢到商品的價(jià)格
    Product productWang = mapper.selectById(1);
    // +50
    productLi.setPrice(productLi.getPrice() + 50);
    mapper.updateById(productLi);
    // -20
    productWang.setPrice(productWang.getPrice() - 20);
    mapper.updateById(productWang);

    // 查詢最終的商品價(jià)格
    System.out.println("最終價(jià)格為:" + mapper.selectById(1).getPrice());
}

// 控制臺(tái)最終打印    ->     最終價(jià)格為:80

??有問(wèn)題就有解決問(wèn)題的方法,出現(xiàn)這個(gè)問(wèn)題的原因就是兩個(gè)管理員同時(shí)獲取到了商品的信息并對(duì)他進(jìn)行了修改,如果可以使用鎖限制同一時(shí)間只能有一個(gè)管理員對(duì)數(shù)據(jù)進(jìn)行修改操作的話,就可以避免這個(gè)問(wèn)題了,這就是悲觀鎖。

??不對(duì)啊,不是說(shuō)要講樂(lè)觀鎖的嘛怎么講到了悲觀鎖了?悲觀鎖將整張表鎖住了,阻止其他人對(duì)表進(jìn)行修改操作,這樣的話對(duì)效率有很大的折損。于是樂(lè)觀鎖應(yīng)運(yùn)而生,樂(lè)觀鎖允許任何人任何時(shí)候?qū)Ρ碇袛?shù)據(jù)進(jìn)行修改,只不過(guò)數(shù)據(jù)表中要添加一個(gè)字段表示數(shù)據(jù)的當(dāng)前版本號(hào),數(shù)據(jù)每經(jīng)過(guò)一次更新版本號(hào)就相應(yīng)加一,數(shù)據(jù)每次更新的時(shí)候都會(huì)帶上版本號(hào)字段作為更新的條件。這樣的話就可以避免之前的問(wèn)題了,兩人同時(shí)獲取到的版本都是0,小李修改之后就會(huì)將版本字段值加一也就是1,這時(shí)小王修改的時(shí)候就會(huì)查不到表中版本號(hào)為0的數(shù)據(jù)而無(wú)法修改。

??這樣的話就會(huì)避免修改沖突,但是還是無(wú)法得到想要的結(jié)果,于是可以對(duì)兩人的修改結(jié)果進(jìn)行判斷,如果更新操作的返回結(jié)果不是0的話就說(shuō)明更新成功,否則就再次獲取數(shù)據(jù)表中的信息(這次就是為了獲得最新的版本號(hào))再次進(jìn)行更新操作

??使用MP中的樂(lè)觀鎖插件,首先需要在配置類中將樂(lè)觀鎖插件添加到攔截器中,然后再在實(shí)體類中的版本號(hào)字段上使用@Version標(biāo)志,然后就是和平常一樣的操作數(shù)據(jù)庫(kù)即可,執(zhí)行更新操作的時(shí)候會(huì)自動(dòng)將當(dāng)前查詢到的版本號(hào)當(dāng)做條件拼接到SQL語(yǔ)句中

// 將樂(lè)觀鎖插件添加到攔截器中
interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());

// 實(shí)體類標(biāo)注版本號(hào)
@Version
private Integer version;

// 測(cè)試方法,測(cè)試兩個(gè)人最后的修改結(jié)果
@Test
public void happyLockTest() {
    // 小李查詢商品的價(jià)格
    Product productLi = mapper.selectById(1);
    // 小王查詢到商品的價(jià)格
    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);
    // 查詢最終的商品價(jià)格
    System.out.println("最終價(jià)格為:" + mapper.selectById(1).getPrice());
}

// 控制臺(tái)最終打印    ->     最終價(jià)格為:130

通用枚舉類

??對(duì)于表中擁有固定幾個(gè)值的一些字段,可以使用枚舉類將比較簡(jiǎn)單的數(shù)字或字符存入到數(shù)據(jù)庫(kù)表中,然后將這個(gè)簡(jiǎn)單的數(shù)字或字符對(duì)應(yīng)著其具體的字符串表示,比如性別0代表女1代表男。這樣就會(huì)減輕數(shù)據(jù)庫(kù)的存儲(chǔ)壓力,提高用戶的使用體驗(yàn)。 使用MP的通用枚舉必須先創(chuàng)建一個(gè)枚舉類,向外提供屬性的getter方法和全參構(gòu)造器,并使用@EnumValue注解將標(biāo)識(shí)的屬性值在數(shù)據(jù)庫(kù)中存儲(chǔ)

@Getter
@AllArgsConstructor
public enum SexEnum {

    FEMALE(0, "女"),
    MALE(1, "男");

    // 將注解標(biāo)識(shí)的屬性值存儲(chǔ)到數(shù)據(jù)庫(kù)中
    @EnumValue
    private Integer sex;
    private String sexName;
}

??然后實(shí)體類中修改字段對(duì)應(yīng)屬性的類型為枚舉類型,然后重寫toString方法,方便查詢結(jié)果顯示為數(shù)據(jù)表中數(shù)字或字符對(duì)應(yīng)的具體的字符串表示

// 修改字段對(duì)應(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è)置通用枚舉的包,也就是相當(dāng)于讓你寫的枚舉類生效

mybatis-plus:
  # 設(shè)置通用枚舉的包
  type-enums-package: com.xiaochen.enums

測(cè)試

@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);
}

測(cè)試結(jié)果

Mybatis-Plus進(jìn)階分頁(yè),樂(lè)觀鎖插件,通用枚舉和多數(shù)據(jù)源實(shí)例分析

多數(shù)據(jù)源

??多數(shù)據(jù)源就是在一個(gè)程序中同時(shí)配置多個(gè)數(shù)據(jù)庫(kù)作為數(shù)據(jù)源進(jìn)行操作,適用于多種場(chǎng)景:純粹多庫(kù)、 讀寫分離、 一主多從、 混合模式等。目前我們就來(lái)模擬一個(gè)純粹多庫(kù)的一個(gè)場(chǎng)景,配置兩個(gè)數(shù)據(jù)庫(kù)的兩張表,通過(guò)一個(gè)測(cè)試用例分別獲取兩張表的數(shù)據(jù),如果獲取到說(shuō)明多庫(kù)模擬成功

第一步: 導(dǎo)入依賴

<!--mybatis-的場(chǎng)景啟動(dòng)器-->
<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è)置默認(rèn)的數(shù)據(jù)源或者數(shù)據(jù)源組,當(dāng)設(shè)置的數(shù)據(jù)源都找不到時(shí)使用默認(rèn)數(shù)據(jù)源,默認(rèn)值即為master
primary: master
# 嚴(yán)格匹配數(shù)據(jù)源,默認(rèn)false.true未匹配到指定數(shù)據(jù)源時(shí)拋異常,false匹配不到指定數(shù)據(jù)源時(shí)使用默認(rèn)數(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

第三步: 照常使用方法測(cè)試在兩個(gè)數(shù)據(jù)庫(kù)查詢兩張表,唯一不同的就是在service的實(shí)現(xiàn)類上使用@DS注解,標(biāo)注service實(shí)現(xiàn)類的所有方法都是對(duì)指定數(shù)據(jù)源進(jìn)行操作的

Mybatis-Plus進(jìn)階分頁(yè),樂(lè)觀鎖插件,通用枚舉和多數(shù)據(jù)源實(shí)例分析

測(cè)試類及結(jié)果

Mybatis-Plus進(jìn)階分頁(yè),樂(lè)觀鎖插件,通用枚舉和多數(shù)據(jù)源實(shí)例分析

關(guān)于“Mybatis-Plus進(jìn)階分頁(yè),樂(lè)觀鎖插件,通用枚舉和多數(shù)據(jù)源實(shí)例分析”這篇文章的內(nèi)容就介紹到這里,感謝各位的閱讀!相信大家對(duì)“Mybatis-Plus進(jìn)階分頁(yè),樂(lè)觀鎖插件,通用枚舉和多數(shù)據(jù)源實(shí)例分析”知識(shí)都有一定的了解,大家如果還想學(xué)習(xí)更多知識(shí),歡迎關(guān)注億速云行業(yè)資訊頻道。

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI