偷偷摘套内射激情视频,久久精品99国产国产精,中文字幕无线乱码人妻,中文在线中文a,性爽19p

MyBatis-Plus 深度指南:從基礎(chǔ)到實戰(zhàn),讓 DAO 層開發(fā)效率起飛

開發(fā) 前端
MyBatis-Plus 可以理解為「MyBatis + 瑞士軍刀皮膚 + 防刪庫保險栓」—— 它在保留 MyBatis 原生特性的基礎(chǔ)上,通過 "零侵入" 設(shè)計實現(xiàn)了單表操作的極簡開發(fā)。

1、MyBatis-Plus 簡介:不止是增強(qiáng),更是重構(gòu)

2、核心功能:單表操作的 "全能工具箱"

2.1 基礎(chǔ) CRUD:單表操作 "零代碼" 實現(xiàn)

2.2 條件構(gòu)造器:復(fù)雜查詢 "優(yōu)雅編碼"

2.3 豐富的插件集合:功能擴(kuò)展的 "萬能接口"

3、使用建議:寫出高效、安全的 MP 代碼

3.1 優(yōu)先使用 Lambda 條件構(gòu)造器

3.2 條件構(gòu)造器 NULL 值處理:減少冗余代碼

3.3 盡量明確 select 字段:提升查詢效率

4、開發(fā)實戰(zhàn):從 "能用" 到 "用好" 的進(jìn)階(重點)

4.1 基礎(chǔ)能力:微服務(wù)下的查詢條件封裝

4.2 快速接入:3 步實現(xiàn)單表 CRUD 接口

4.3 豐富 BaseMapper:擴(kuò)展自定義通用方法

4.4 內(nèi)置插件:增強(qiáng)系統(tǒng)安全性

5、總結(jié):為什么 MyBatis-Plus 值得用?

1、MyBatis-Plus 簡介:不止是增強(qiáng),更是重構(gòu)

MyBatis-Plus 可以理解為「MyBatis + 瑞士軍刀皮膚 + 防刪庫保險栓」—— 它在保留 MyBatis 原生特性的基礎(chǔ)上,通過 "零侵入" 設(shè)計實現(xiàn)了單表操作的極簡開發(fā)。

其核心價值體現(xiàn)在三方面:

  • 瑞士軍刀般的便捷性:將 XML 配置的 "青銅時代" 升級為 Lambda 表達(dá)式的 "賽博坦時代",用極簡代碼實現(xiàn)復(fù)雜操作;
  • 保險栓級的安全性:通過攔截器讓 "delete from table" 這類危險操作成為不可能,從源頭避免刪庫風(fēng)險;
  • 零侵入的兼容性:無需修改現(xiàn)有 MyBatis 代碼,老項目可平滑遷移,既保留原生 SQL 靈活性,又獲得增強(qiáng)功能。

2、核心功能:單表操作的 "全能工具箱"

MyBatis-Plus 的核心功能是圍繞單表的 CRUD 展開的,覆蓋從基礎(chǔ)操作到高級查詢的全場景,所有功能均通過 BaseMapper 接口暴露,無需手動實現(xiàn)。

2.1 基礎(chǔ) CRUD:單表操作 "零代碼" 實現(xiàn)

BaseMapper 中封裝了單表所有基礎(chǔ)操作,無需手寫 SQL 就能滿足 90% 的業(yè)務(wù)需求。關(guān)鍵方法整理如下:

操作類型

方法示例

作用

注意事項

新增

int insert(T entity)

插入一條記錄,返回影響行數(shù)

自動忽略 entity 中 null 值的屬性

新增 / 更新

boolean insertOrUpdate(T entity)

若記錄存在則更新,否則插入

依賴主鍵查詢(建議查主庫避免主從延遲)

刪除

int deleteById(Serializable id)

根據(jù)主鍵刪除單條記錄

物理刪除,數(shù)據(jù)恢復(fù)需 DBA 協(xié)助

刪除

int deleteByIds(Collection<?> idList)

批量刪除主鍵對應(yīng)的記錄

需手動控制 idList 大小,防止數(shù)據(jù)庫負(fù)載過高

更新

int updateById(T entity)

根據(jù)主鍵更新記錄

主鍵必須非空,忽略 null 值屬性(避免 WHERE id=NULL)

查詢

T selectById(Serializable id)

根據(jù)主鍵查詢單條記錄

-

查詢

List<T> selectList(Wrapper<T> queryWrapper)

根據(jù)條件批量查詢

queryWrapper 為 null 時會全表掃描,需謹(jǐn)慎

2.2 條件構(gòu)造器:復(fù)雜查詢 "優(yōu)雅編碼"

條件構(gòu)造器是 MyBatis-Plus 的 "靈魂",支持用面向?qū)ο蟮姆绞綐?gòu)建 SQL 條件,避免字符串拼接的坑。核心實現(xiàn)有 4 種:

  • QueryWrapper:基礎(chǔ)條件構(gòu)造器,通過字符串指定字段(如 eq("name", "張三"));
  • LambdaQueryWrapper:基于 Lambda 表達(dá)式的構(gòu)造器(如 eq(User::getName, "張三")),推薦優(yōu)先使用;
  • UpdateWrapper/LambdaUpdateWrapper:用于構(gòu)建更新條件,支持動態(tài)設(shè)置 set 值。

為什么優(yōu)先用 LambdaQueryWrapper?

對比傳統(tǒng)寫法的優(yōu)勢一目了然:

// ? 不推薦:字段拼寫錯誤編譯不報錯,字段變更易遺漏
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "張三").gt("age", 18);

// ? 推薦:編譯期檢查字段有效性,重構(gòu)自動更新引用
LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();
lambdaQueryWrapper.eq(User::getName, "張三").gt(User::getAge, 18);

優(yōu)勢體現(xiàn)在:

  • 防止字段拼寫錯誤導(dǎo)致的 SQL 異常(編譯期校驗);
  • 自動校驗值類型,避免因類型不匹配導(dǎo)致索引失效;
  • 提高代碼可讀性,字段含義一目了然。

2.3 豐富的插件集合:功能擴(kuò)展的 "萬能接口"

MyBatis-Plus 通過 MybatisPlusInterceptor 實現(xiàn)插件機(jī)制,可攔截 SQL 執(zhí)行過程并增強(qiáng)功能,核心插件如下:

插件名稱

作用

關(guān)鍵說明

PaginationInnerInterceptor

自動分頁

必須配置,否則會內(nèi)存分頁(不拼接 limit)

BlockAttackInnerInterceptor

防止全表更新 / 刪除

攔截不帶 WHERE 條件的 update/delete,避免誤操作

OptimisticLockerInnerInterceptor

樂觀鎖

通過版本號字段解決并發(fā)更新沖突

TenantLineInnerInterceptor

多租戶

自動為 SQL 添加租戶 ID 條件,隔離數(shù)據(jù)

IllegalSQLInnerInterceptor

SQL 性能規(guī)范

攔截不符合規(guī)范的 SQL(如 SELECT *)

3、使用建議:寫出高效、安全的 MP 代碼

3.1 優(yōu)先使用 Lambda 條件構(gòu)造器

再強(qiáng)調(diào)一次:別用字符串拼條件!LambdaQueryWrapper 能在編譯期幫你擋住 "字段不存在"、"類型不匹配" 等一堆坑,重構(gòu)時還能自動更新引用 —— 相當(dāng)于給代碼加了 "自動糾錯"buff。

3.2 條件構(gòu)造器 NULL 值處理:減少冗余代碼

當(dāng)查詢條件含 null 值時,傳統(tǒng)寫法需用 if 判斷避免無效條件,MP 支持 "條件性添加",一行代碼搞定:

// ? 不推薦:大量if判斷
LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
if (StringUtils.isNotBlank(name)) {
    wrapper.eq(User::getName, name);
}
if (age != null) {
    wrapper.eq(User::getAge, age);
}

// ? 推薦:條件性添加,減少冗余
wrapper.eq(StringUtils.isNotBlank(name), User::getName, name)
       .eq(Objects.nonNull(age), User::getAge, age);

優(yōu)勢:減少 if 判斷、避免無效查詢條件。

3.3 盡量明確 select 字段:提升查詢效率

默認(rèn)情況下,selectList 會查詢所有字段(select *),指定查詢字段可利用索引覆蓋、減少數(shù)據(jù)傳輸:

// ? 不推薦:全表字段查詢,浪費資源
List<User> users1 = userMapper.selectList(lambdaQueryWrapper);

// ? 推薦:只查詢需要的字段
lambdaQueryWrapper.select(User::getId, User::getName, User::getAge);
List<User> users2 = userMapper.selectList(lambdaQueryWrapper);

優(yōu)勢體現(xiàn)在:

  • 利用索引覆蓋,避免回表查詢,提升 SQL 效率;
  • 減少數(shù)據(jù)傳輸和序列化開銷,降低數(shù)據(jù)庫壓力;
  • 節(jié)省內(nèi)存,尤其對大表查詢效果明顯。

4、開發(fā)實戰(zhàn):從 "能用" 到 "用好" 的進(jìn)階(重點)

在實際項目中,尤其是微服務(wù)架構(gòu)下,需要將dao層作為單獨的服務(wù)對外提供原子能力,此時必須解決 QueryWrapper 在 RPC 場景的痛點,同時實現(xiàn)高效接入、功能擴(kuò)展及安全保障。

4.1 基礎(chǔ)能力:微服務(wù)下的查詢條件封裝

4.1.1 痛點與解決方案

在微服務(wù)中,若將 DAO 層封裝為獨立服務(wù),直接暴露 QueryWrapper 存在 3 大問題:

  • QueryWrapper 結(jié)構(gòu)復(fù)雜,序列化 / 反序列化耗時;
  • 邏輯層需引入 mybatis-plus-core 依賴,易導(dǎo)致 Jar 包沖突;
  • 原子層升級 MP 版本時,所有調(diào)用方需同步升級,維護(hù)成本高。

解決方案:自定義 QueryCondition 替代 QueryWrapper,作為 RPC 入?yún)?,兼顧靈活性與輕量性。

4.1.2 QueryCondition 設(shè)計

QueryCondition 整合查詢、排序、分頁及字段選擇能力,結(jié)構(gòu)如下:

  • 查詢條件集合(queryFieldList):封裝 WHERE 子句的條件,包含字段名、匹配規(guī)則(如等于、模糊查詢)、拼接方式(AND/OR);
  • 排序字段集合(orderFieldList):定義排序字段及排序方式(ASC/DESC);
  • 返回字段集合(selectFieldList):指定查詢結(jié)果需返回的字段,避免 select *;
  • 分頁參數(shù):頁碼(pageNum)和每頁條數(shù)(pageSize)。
// 綜合查詢條件類
public class QueryCondition {
    private List<String> selectFieldList; // 返回字段
    private List<QueryField> queryFieldList; // 查詢條件
    private List<OrderField> orderFieldList; // 排序字段
    private int pageNum;  // 頁碼
    private int pageSize; // 每頁條數(shù)
}

4.1.3 類型安全的構(gòu)建工具:QueryConditionBuilder

為簡化 QueryCondition 的創(chuàng)建,設(shè)計 QueryConditionBuilder 工具類,通過 Lambda 表達(dá)式實現(xiàn)類型安全構(gòu)建:

public class QueryConditionBuilder<T> {
    private List<SelectFieldBuilder<T>> selectFieldBuilderList; // 返回字段構(gòu)建
    private List<QueryFieldBuilder<T>> queryFieldBuilderList; // 查詢條件構(gòu)建
    private List<OrderFieldBuilder<T>> orderFieldBuilderList; // 排序字段構(gòu)建
}

使用示例:

@Test
public void selectByQuery() {
    QueryConditionBuilder<User> builder = QueryConditionBuilder.builder();
    QueryCondition condition = builder
        .select(User::getId, User::getName) // 選擇返回字段
        .eq(User::getStatus, 1) // 相等查詢
        .like(User::getName, "張") // 模糊查詢
        .in(User::getType, Arrays.asList(1, 2, 3)) // 集合查詢
        .orderByDesc(User::getCreateTime) // 排序
        .pageNum(1) // 頁碼
        .pageSize(5) // 每頁條數(shù)
        .build(); // 構(gòu)建時校驗數(shù)據(jù)類型,不匹配則拋異常
}

4.1.4 接口與實現(xiàn)設(shè)計

  • 接口定義:在 dao-contract 中定義通用接口 BaseDao,對外暴露單表操作的CRUD能力
public interface BaseDao<P extends Serializable, T> {
    @Master
    T insert(T entity, Option... option); // 新增
    @Slave
    List<T> selectListByQuery(QueryCondition queryCondition, Option... option); // 條件查詢

    // 其他方法...
}
  • 實現(xiàn)設(shè)計:在 dao-service 通過抽象類 AbstractBaseDaoImpl 繼承 MyBatis-Plus 的 ServiceImpl,并實現(xiàn) BaseDao 接口,在抽象類中將自定義的 QueryCondition 轉(zhuǎn)換成 LambdaQueryWrapper 再調(diào)用 ServiceImpl 中的方法實現(xiàn) BaseDao 中對外暴漏的所有方法:

圖片圖片

public abstract class AbstractBaseDaoImpl<P extends Serializable, T, M extends BaseMapper<T>> 
        extends ServiceImpl<M, T> implements BaseDao<P, T> {
            
            @Override
            public T insert(T entity, Option... option) {
                // 適配自定義配置項
                this.beforeOption(option);
                try {
                    if (Objects.nonNull(entity)) {
                        super.save(entity);
                    }
                    return entity;
                } finally {
                    // 回滾自定義配置項
                    this.afterOption(option);
                }
            }
               
            @Override
            public List<T> selectListByQuery(QueryCondition queryCondition, Option... option) {
                if (Objects.isNull(queryCondition)) {
                    return new ArrayList<>();
                }
                this.beforeOption(option);
                try {
                    final Wrapper<T> queryWrapper = this.queryCondition2QueryWrapper(queryCondition);
                    return super.list(queryWrapper);
                } finally {
                    this.afterOption(option);
                }
            }

            // ...... 其他方法的實現(xiàn)
}

4.1.5 整體架構(gòu)

采用分層架構(gòu)實現(xiàn)高內(nèi)聚低耦合:

kf_scaffold/
├── dao-contract/    # 接口定義層:暴露對外RPC接口
├── dao-service/     # 服務(wù)實現(xiàn)層:實現(xiàn)接口,依賴MyBatis-Plus
├── dao-plugin/      # 插件擴(kuò)展層:自定義插件(如全表攔截)
├── dao-spring-boot-starter/  # 自動配置層:封裝Starter,簡化接入
└── dao-demo/        # 使用示例層:提供接入示例

4.2 快速接入:3 步實現(xiàn)單表 CRUD 接口

以售后單表(AssOrder)為例,快速搭建對外暴露的 CRUD 服務(wù):

4.2.1 接口層工程(ass-dao-contract)

  • 引入依賴:
<dependency>
    <groupId>com.bj58.zhuanzhuan.kf</groupId>
    <artifactId>dao-contract</artifactId>
</dependency>
  • 定義實體
// 售后單據(jù)
public class AssOrderEntity {
    private Long id; // 售后單ID
    // 其他字段...
}
  • 定義接口:繼承 BaseDao,無需編寫方法實現(xiàn)
// 售后單表的 CRUD 接口
public interface IAssOrderDao extends BaseDao<Long, AssOrderEntity> {
}

4.2.2 服務(wù)層工程(ass-dao-service)

  • 引入依賴
<dependency>
    <groupId>com.bj58.zhuanzhuan.kf</groupId>
    <artifactId>dao-spring-boot-starter</artifactId>
</dependency>
  • 配置數(shù)據(jù)源:區(qū)分主從庫,實現(xiàn)讀寫分離
kf:
  dao:
    data-source:
      master:
        url: jdbc:mysql://localhost:3306/master_db
        driver-class-name: com.mysql.cj.jdbc.Driver
      slave:
        url: jdbc:mysql://localhost:3306/slave_db
        driver-class-name: com.mysql.cj.jdbc.Driver
  • 編寫實現(xiàn):繼承 AbstractBaseDaoImpl,無需手動實現(xiàn)方法
// 售后單表的 CRUD 接口實現(xiàn)
public class AssOrderDao extends AbstractBaseDaoImpl<Long, AssOrderEntity, AssOrderMapper> 
        implements IAssOrderDao {
}

效果:通過上述步驟,無需編寫 SQL,即可對外提供 AssOrder 表的 CRUD 接口,支持通過 QueryCondition 進(jìn)行條件查詢、排序、分頁等操作。

4.3 豐富 BaseMapper:擴(kuò)展自定義通用方法

BaseMapper 的默認(rèn)方法若不滿足需求(如按實體屬性統(tǒng)計數(shù)量),可按以下步驟擴(kuò)展:

4.3.1 自定義 Mapper 接口

定義 MyMapper 繼承 BaseMapper,添加自定義方法:

public interface MyMapper<T> extends BaseMapper<T> {
    // 按實體屬性拼接AND條件統(tǒng)計數(shù)量
    int countByEntity(T entity);
}

4.3.2 注入方法實現(xiàn)

通過 AbstractMethod 構(gòu)建 SQL 模板,實現(xiàn) countByEntity 的邏輯:

public class CountByEntityMethod extends AbstractMethod {
    private static final String SQL_TEMPLATE = "<script>%s SELECT COUNT(%s) FROM %s %s %s\n</script>";
    
    @Override
    public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {
        String sql = String.format(SQL_TEMPLATE, 
            sqlFirst(),                // 前置SQL
            selectColumns(tableInfo, true),  // 計數(shù)字段
            tableInfo.getTableName(),  // 表名
            sqlWhereEntityWrapper(true, tableInfo),  // WHERE條件(基于實體屬性)
            sqlComment());             // 注釋
        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);
        return addSelectMappedStatementForOther(mapperClass, "countByEntity", sqlSource, Integer.class);
    }
}

4.3.3 注冊自定義方法

通過 SqlInjector 將自定義方法注入 MyBatis-Plus:

// 自定義注入器
public class MySqlInjector extends DefaultSqlInjector {
    @Override
    public List<AbstractMethod> getMethodList(Class<?> mapperClass, TableInfo tableInfo) {
        List<AbstractMethod> methods = super.getMethodList(mapperClass, tableInfo);
        methods.add(new CountByEntityMethod()); // 添加自定義方法
        return methods;
    }
}

// 配置注入器,將自定義注入器放入spring環(huán)境中
@Configuration
publicclass MybatisPlusConfig {
    @Bean
    public MySqlInjector customSqlInjector() {
        return new MySqlInjector();
    }
}

4.3.4 使用擴(kuò)展方法

// 定義 UserMapper 繼承自定義的 MyMapper
@Mapper
public interface UserMapper extends MyMapper<User> {
}

// 調(diào)用示例
@Test
public void testCountByEntity() {
    User user = new User();
    user.setName("張三"); // 按姓名統(tǒng)計
    int count = userMapper.countByEntity(user); 
    System.out.println("符合條件的用戶數(shù):" + count);
}

4.4 內(nèi)置插件:增強(qiáng)系統(tǒng)安全性

為避免生產(chǎn)環(huán)境中的誤操作,在dao-plugin工程中定義了兩個插件:

4.4.1 全表掃描攔截(FullTableScanInterceptor)

  • 功能:攔截?zé)o查詢條件的 SQL(如 select * from user),防止全表掃描導(dǎo)致的性能問題;
  • 場景:當(dāng) QueryCondition 未設(shè)置查詢條件時,自動攔截并拋異常。

4.4.2 全表更新攔截(BlockFullTableOperationInterceptor)

  • 功能:攔截?zé)o更新條件的 SQL(如 update user set status=0),防止全表更新;
  • 價值:避免因條件構(gòu)造器錯誤導(dǎo)致的批量數(shù)據(jù)修改,從源頭降低風(fēng)險。

5、總結(jié):為什么 MyBatis-Plus 值得用?

MyBatis-Plus 的核心價值在于:用最小的改造成本,實現(xiàn) DAO 層開發(fā)效率的質(zhì)的飛躍。

  • 對開發(fā)者:減少 90% 的 CRUD 代碼,用 Lambda 替代字符串拼接,從 "寫 SQL" 轉(zhuǎn)向 "拼條件";
  • 對系統(tǒng):通過插件機(jī)制增強(qiáng)安全性(防刪庫、SQL 規(guī)范)和可擴(kuò)展性(分頁、多租戶);
  • 對團(tuán)隊:降低新人上手成本,統(tǒng)一 DAO 層編碼規(guī)范,減少因 SQL 問題導(dǎo)致的線上故障。

關(guān)于作者

孟建國,轉(zhuǎn)轉(zhuǎn)履約中臺研發(fā)工程師,主要負(fù)責(zé)售后業(yè)務(wù)

責(zé)任編輯:武曉燕 來源: 轉(zhuǎn)轉(zhuǎn)技術(shù)
相關(guān)推薦

2024-12-20 16:49:15

MyBatis開發(fā)代碼

2025-02-27 09:45:47

2025-07-17 13:52:57

通配符Linux命令行

2023-06-07 08:08:37

MybatisSpringBoot

2023-07-29 22:02:06

MyBatis數(shù)據(jù)庫配置

2025-09-26 02:00:55

JDKCPU內(nèi)存

2023-06-14 08:34:18

Mybatis死鎖框架

2024-07-03 10:09:29

2023-10-31 08:01:48

Mybatis參數(shù)jdbcurl?

2023-06-07 08:00:00

MySQL批量插入

2025-10-09 01:33:00

2025-10-28 01:15:00

2025-06-27 06:30:08

2024-10-22 16:59:07

2024-07-31 09:56:20

2025-05-26 03:20:00

SpringMyBatis數(shù)據(jù)權(quán)限

2021-02-22 11:12:24

ExcelPython數(shù)據(jù)

2025-07-10 09:32:23

2024-11-28 19:03:56

2024-02-28 09:35:52

點贊
收藏

51CTO技術(shù)棧公眾號