MyBatisPlus之CRUD接口(IService與BaseMapper)

MyBatisPlus之CRUD接口—IService與BaseMapper

    • 一、BaseMapper與IService的關系
    • 二、BaseMapper核心方法詳解
      • 2.1 新增操作(Insert)
      • 2.2 查詢操作(Select)
      • 2.3 更新操作(Update)
      • 2.4 刪除操作(Delete)
    • 三、IService核心方法詳解
      • 3.1 新增操作(Save)
      • 3.2 查詢操作(Get/List)
      • 3.3 更新操作(Update)
      • 3.4 刪除操作(Remove)
      • 3.5 其他實用方法
    • 四、BaseMapper與IService的選擇策略
    • 五、實戰技巧與避坑指南
      • 5.1 Wrapper的靈活使用
      • 5.2 批量操作的性能優化
      • 5.3 避免N+1查詢問題
      • 5.4 邏輯刪除與查詢的注意事項

MyBatisPlus(MP)的核心優勢之一是提供了開箱即用的CRUD接口,通過BaseMapper(DAO層)和IService(Service層)封裝了單表操作的常用方法,無需編寫SQL即可完成大部分數據庫操作。

一、BaseMapper與IService的關系

在MyBatisPlus中,BaseMapperIService是實現CRUD操作的兩大核心接口,二者分工明確又相互配合:

  • BaseMapper:位于DAO層,直接與數據庫交互,提供基礎的CRUD方法(如insertselectById),需由用戶自定義的Mapper接口繼承。
  • IService:位于Service層,基于BaseMapper封裝了更豐富的業務方法(如批量操作、分頁查詢),并提供事務支持,需由用戶自定義的Service接口繼承。

調用關系IService的實現類(如ServiceImpl)會注入BaseMapper實例,通過調用BaseMapper的方法完成數據庫操作,同時添加業務邏輯和事務控制。

使用建議

  • 簡單查詢直接使用BaseMapper
  • 復雜業務(如批量操作、事務管理)優先使用IService
  • 自定義SQL通過BaseMapper的方法擴展。

二、BaseMapper核心方法詳解

BaseMapper<T>是MP的基礎接口,泛型T為實體類類型。所有自定義Mapper接口只需繼承它,即可獲得17個基礎CRUD方法。

2.1 新增操作(Insert)

方法簽名功能描述示例
int insert(T entity)插入一條記錄userMapper.insert(user)

說明

  • 插入時會根據實體類的注解(如@TableId)自動處理主鍵生成;
  • 若字段未設置值,會插入null(除非配置了自動填充);
  • 返回值為受影響的行數(成功插入返回1)。

示例

User user = new User();
user.setUsername("張三");
user.setAge(20);
user.setEmail("zhangsan@example.com");
int rows = userMapper.insert(user); // 插入成功后,user.getId()會自動回填主鍵
System.out.println("插入行數:" + rows + ",生成ID:" + user.getId());

2.2 查詢操作(Select)

BaseMapper提供了7種查詢方法,覆蓋單條查詢、批量查詢、條件查詢等場景:

方法簽名功能描述適用場景
T selectById(Serializable id)根據ID查詢已知主鍵的單條查詢
List<T> selectBatchIds(Collection<?> ids)批量查詢(根據ID集合)批量獲取多條記錄
List<T> selectByMap(Map<String, Object> map)根據Map條件查詢簡單條件查詢(鍵為字段名)
T selectOne(@Param("ew") Wrapper<T> queryWrapper)根據條件查詢單條確保結果唯一的查詢(如唯一索引)
Integer selectCount(@Param("ew") Wrapper<T> queryWrapper)條件查詢總數統計符合條件的記錄數
List<T> selectList(@Param("ew") Wrapper<T> queryWrapper)條件查詢列表復雜條件的多條查詢
List<Map<String, Object>> selectMaps(@Param("ew") Wrapper<T> queryWrapper)條件查詢(返回Map)只需要部分字段,無需實體類

示例1:根據ID查詢

User user = userMapper.selectById(1L); // ID為1的用戶

示例2:批量查詢

List<Long> ids = Arrays.asList(1L, 2L, 3L);
List<User> users = userMapper.selectBatchIds(ids); // 查詢ID為1、2、3的用戶

示例3:條件查詢(使用QueryWrapper)

// 查詢年齡≥20且用戶名包含"張"的用戶
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.ge("age", 20) // 年齡≥20.like("username", "張"); // 用戶名含"張"
List<User> users = userMapper.selectList(queryWrapper);

示例4:查詢總數

// 統計年齡<18的用戶數量
Integer count = userMapper.selectCount(new QueryWrapper<User>().lt("age", 18)
);

2.3 更新操作(Update)

方法簽名功能描述適用場景
int updateById(@Param("et") T entity)根據ID更新已知主鍵,更新部分字段
int update(@Param("et") T entity, @Param("ew") Wrapper<T> updateWrapper)根據條件更新按條件批量更新

示例1:根據ID更新

User user = new User();
user.setId(1L); // 必須設置ID
user.setAge(21); // 只更新年齡
int rows = userMapper.updateById(user); // SQL:UPDATE user SET age=21 WHERE id=1

示例2:條件更新

// 將所有年齡<18的用戶狀態改為"禁用"
User user = new User();
user.setStatus(StatusEnum.DISABLE);UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.lt("age", 18); // 條件:年齡<18int rows = userMapper.update(user, updateWrapper); 
// SQL:UPDATE user SET status=0 WHERE age < 18

2.4 刪除操作(Delete)

方法簽名功能描述適用場景
int deleteById(Serializable id)根據ID刪除刪除單條記錄
int deleteBatchIds(Collection<?> ids)批量刪除(根據ID集合)批量刪除多條記錄
int deleteByMap(Map<String, Object> map)根據Map條件刪除簡單條件的批量刪除
int delete(@Param("ew") Wrapper<T> queryWrapper)根據條件刪除復雜條件的批量刪除

示例1:根據ID刪除

int rows = userMapper.deleteById(1L); // 刪除ID為1的用戶

示例2:條件刪除

// 刪除郵箱為空的用戶
int rows = userMapper.delete(new QueryWrapper<User>().isNull("email")
);

三、IService核心方法詳解

IService<T>是Service層的接口,基于BaseMapper擴展了更豐富的方法,尤其適合復雜業務場景。自定義Service接口需繼承IService,實現類需繼承ServiceImpl<Mapper, T>

3.1 新增操作(Save)

方法簽名功能描述與BaseMapper的區別
boolean save(T entity)插入一條記錄返回boolean(成功/失敗),BaseMapper返回int
boolean saveBatch(Collection<T> entityList)批量插入內部默認分批插入(默認1000條/批)
boolean saveBatch(Collection<T> entityList, int batchSize)自定義批次大小的批量插入可指定每批插入數量

示例1:單條插入

User user = new User();
user.setUsername("李四");
boolean success = userService.save(user); // 成功返回true

示例2:批量插入

List<User> userList = new ArrayList<>();
for (int i = 0; i < 100; i++) {User user = new User();user.setUsername("用戶" + i);user.setAge(18 + i % 20);userList.add(user);
}
// 批量插入(默認每批1000條)
boolean success = userService.saveBatch(userList);
// 自定義每批50條
// userService.saveBatch(userList, 50);

3.2 查詢操作(Get/List)

IService的查詢方法在BaseMapper基礎上增加了分頁查詢和鏈式調用支持:

方法簽名功能描述特色功能
T getById(Serializable id)根據ID查詢selectById,返回null時無異常
List<T> listByIds(Collection<?> ids)批量查詢(ID集合)selectBatchIds
List<T> list(Wrapper<T> queryWrapper)條件查詢列表selectList
IPage<T> page(IPage<T> page, Wrapper<T> queryWrapper)分頁查詢支持分頁插件,返回分頁對象
long count(Wrapper<T> queryWrapper)條件查詢總數selectCount,返回long類型
boolean exists(Wrapper<T> queryWrapper)判斷是否存在符合條件的記錄簡化count > 0的判斷

示例1:分頁查詢

// 分頁查詢:第2頁,每頁10條,條件:年齡≥20
Page<User> page = new Page<>(2, 10); // 頁碼從1開始
IPage<User> userPage = userService.page(page, new QueryWrapper<User>().ge("age", 20)
);List<User> records = userPage.getRecords(); // 當前頁數據
long total = userPage.getTotal(); // 總條數
long pages = userPage.getPages(); // 總頁數

示例2:判斷記錄是否存在

// 判斷是否存在用戶名=張三的用戶
boolean exists = userService.exists(new QueryWrapper<User>().eq("username", "張三")
);

3.3 更新操作(Update)

方法簽名功能描述特色功能
boolean updateById(T entity)根據ID更新updateById,返回boolean
boolean update(Wrapper<T> updateWrapper)根據條件更新(無實體類)直接通過Wrapper設置更新字段
boolean update(T entity, Wrapper<T> updateWrapper)根據條件更新BaseMapper.update
boolean updateBatchById(Collection<T> entityList)批量更新(根據ID)批量更新多條記錄
boolean updateBatchById(Collection<T> entityList, int batchSize)自定義批次的批量更新可指定每批更新數量

示例1:通過Wrapper直接更新

// 無需實體類,直接設置更新字段
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("username", "張三") // 條件.set("age", 22) // 更新字段.set("email", "new@example.com");
boolean success = userService.update(updateWrapper);

示例2:批量更新

List<User> userList = new ArrayList<>();
// 假設userList中包含多個設置了ID和待更新字段的User對象
boolean success = userService.updateBatchById(userList);

3.4 刪除操作(Remove)

方法簽名功能描述與BaseMapper的區別
boolean removeById(Serializable id)根據ID刪除返回boolean,BaseMapper返回int
boolean removeByIds(Collection<?> ids)批量刪除(ID集合)deleteBatchIds,返回boolean
boolean remove(Wrapper<T> queryWrapper)根據條件刪除delete,返回boolean
boolean removeByMap(Map<String, Object> map)根據Map條件刪除deleteByMap,返回boolean

示例

// 根據條件刪除
boolean success = userService.remove(new QueryWrapper<User>().eq("status", StatusEnum.DISABLE)
);

3.5 其他實用方法

方法簽名功能描述示例
T getOne(Wrapper<T> queryWrapper, boolean throwEx)查詢單條,支持是否拋異常getOne(wrapper, true) 結果不唯一時拋異常
List<T> list(IPage<T> page, Wrapper<T> queryWrapper)分頁查詢(返回List)只獲取分頁數據,忽略總條數
boolean saveOrUpdate(T entity)新增或更新(根據ID判斷)有ID則更新,無ID則插入
boolean saveOrUpdateBatch(Collection<T> entityList)批量新增或更新批量處理新增/更新

示例:saveOrUpdate(新增或更新)

User user1 = new User();
user1.setId(1L); // 有ID → 更新
user1.setAge(23);User user2 = new User();
user2.setUsername("新用戶"); // 無ID → 新增userService.saveOrUpdate(user1);
userService.saveOrUpdate(user2);

四、BaseMapper與IService的選擇策略

場景推薦使用理由
簡單CRUD操作(單表)優先IService方法返回boolean,更符合業務邏輯判斷;支持批量操作
復雜查詢(多條件)IService + Wrapper鏈式調用更簡潔,支持分頁
事務管理IServiceService層天然適合控制事務(@Transactional
自定義SQLBaseMapper需在Mapper接口中定義方法,通過@Select等注解實現
批量操作(1000+條)IService的批量方法內置分批處理,避免SQL過長導致性能問題
分布式事務IService結合@Transactional(rollbackFor = Exception.class)確保事務一致性

五、實戰技巧與避坑指南

5.1 Wrapper的靈活使用

  • LambdaQueryWrapper:避免硬編碼字段名,推薦使用:

    LambdaQueryWrapper<User> lambdaWrapper = new LambdaQueryWrapper<>();
    lambdaWrapper.ge(User::getAge, 20) // 引用方法,類型安全.like(User::getUsername, "張");
    
  • 條件判斷:通過if動態組裝條件:

    LambdaQueryWrapper<User> wrapper = new LambdaQueryWrapper<>();
    if (minAge != null) {wrapper.ge(User::getAge, minAge);
    }
    if (keyword != null) {wrapper.like(User::getUsername, keyword).or().like(User::getEmail, keyword);
    }
    

5.2 批量操作的性能優化

  • 設置合理的批次大小saveBatch默認每批1000條,可根據數據庫性能調整(如MySQL建議500-1000條/批);
  • 關閉批量操作的自動填充:若無需更新時間等字段,可通過全局配置關閉,提升性能;
  • 使用INSERT INTO ... VALUES (...), (...)語法:MP的批量插入默認使用此語法,比循環單條插入效率高10倍以上。

5.3 避免N+1查詢問題

當查詢列表后需要根據關聯ID查詢其他表時,容易出現N+1問題(1次查列表,N次查詳情)。解決方案:

  • 手動編寫聯表查詢SQL(通過BaseMapper擴展);
  • 使用MP的@TableField關聯查詢(適合簡單關聯);
  • 結合PageHelper等插件實現分頁聯表查詢。

5.4 邏輯刪除與查詢的注意事項

  • 邏輯刪除后,BaseMapperIService的查詢方法會自動過濾已刪除數據(添加is_deleted = 0條件);
  • 自定義SQL需手動添加邏輯刪除。

若這篇內容幫到你,動動手指支持下!關注不迷路,干貨持續輸出!
ヾ(′? ˋ)ノヾ(′? ˋ)ノヾ(′? ˋ)ノヾ(′? ˋ)ノヾ(′? ˋ)ノ

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

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

相關文章

axios請求的取消

axios請求的取消解決&#xff1a;axios請求的取消解決&#xff1a;axios請求的取消 在使用 Axios 發起請求時&#xff0c;有時候你可能需要取消這些請求&#xff0c;比如當組件銷毀時或者用戶操作導致不再需要獲取之前發起的請求結果。Axios 支持通過 Cancel Token 取消請求。 …

深入理解C++中的Lazy Evaluation:延遲計算的藝術

在編程世界里&#xff0c;“最好的運算就是從未執行的運算” —— 這句話深刻揭示了性能優化的核心思路。如果一個計算過程最終不會被使用&#xff0c;那么提前執行它就是純粹的資源浪費。這種思想衍生出了 Lazy Evaluation&#xff08;緩式評估&#xff09; 技術&#xff1a;延…

php完整處理word中表單數據的方法

使用php基礎方式實現word中表單處理<?php/*** zipFile 類用于處理 .docx 文件的解壓、修改和重新打包*/ class zipFile {/** var ZipArchive ZIP 文件對象 */private $zipFile;/** var string 臨時目錄路徑 */private $tempDir;/** var string 嵌入的 Excel 文件臨時目錄路…

Node.js 操作 MongoDB

目錄 Node.js 操作 MongoDB 一、什么是 MongoDB&#xff1f; 二、MongoDB 的功能概覽 三、MongoDB 的安裝與啟動 安裝 MongoDB&#xff08;以本地安裝為例&#xff09; 啟動 MongoDB 四、Node.js 如何連接 MongoDB&#xff1f; 使用 Mongoose ODM 工具 建立連接 五、…

先學Python還是c++?

選擇先學Python還是C&#xff0c;取決于你的學習目標、應用場景和職業規劃。以下是兩者的對比分析和建議&#xff0c;幫助你做出更適合自己的選擇&#xff1a;一、核心差異對比維度PythonC學習曲線簡單易上手&#xff08;語法接近自然語言&#xff09;復雜&#xff08;需理解指…

Trae + Notion MCP:將你的Notion數據庫升級為智能對話機器人

前言 Notion作為一款功能強大的信息管理工具&#xff0c;被廣泛用于項目跟蹤、知識庫構建和數據整理。然而&#xff0c;隨著數據量的增長&#xff0c;我們常常會發現自己陷入了重復和繁瑣的操作中。比如&#xff0c;為了找到符合特定條件的幾條數據&#xff0c;需要在龐大的數…

【iOS】retain/release底層實現原理

文章目錄前言前情知識retain和release的實現原理&#xff08;MRC手動管理&#xff09;retain&#xff08;MRC手動管理&#xff09;retain源碼內聯函數rootRetain源碼相關的sidetable_tryRetain()方法retain底層工作流程總結releaserelease源碼內聯函數rootRelease源碼小結前言 …

文件同步神器-rsync命令講解

rsync 是一個強大的文件同步與傳輸工具&#xff0c;廣泛用于本地或遠程服務器之間的高效文件備份、鏡像或同步。其核心優勢是通過增量傳輸?&#xff08;僅傳輸文件差異部分&#xff09;和壓縮減少數據傳輸量&#xff0c;同時支持保留文件元數據&#xff08;如權限、時間戳、所…

Rust: 工具鏈版本更新

遇到 cargo build --release 錯誤&#xff0c;比如&#xff0c;當前 Rust 工具鏈版本&#xff08;1.78.0&#xff09;低于依賴項所需的最低版本&#xff08;部分依賴要求 ≥1.82.0&#xff09;。以下是系統化的解決方案&#xff1a; &#x1f527; 一、升級 Rust 工具鏈&#x…

Prompt-to-Prompt| 修改Attention會有“反向傳播”或梯度計算?

需要注意的幾個問題&#xff1a;額外計算開銷&#xff1a;Cross-Attention Control原因&#xff1a;Prompt-to-Prompt的編輯方法需要動態干預交叉注意力&#xff08;Cross-Attention&#xff09;層的權重&#xff0c;這會引入額外的計算和顯存占用&#xff1a;需要緩存注意力矩…

電商API接口的優勢、數據采集方法及功能說明

一、電商API接口的核心優勢1. 高效性與準確性數據采集效率&#xff1a;API通過標準化參數&#xff08;如商品ID、類目&#xff09;直接獲取結構化數據&#xff08;JSON/XML&#xff09;&#xff0c;無需解析HTML&#xff0c;減少誤差。例如&#xff0c;采集1000條商品信息&…

iOS企業簽名掉簽,iOS企業簽名掉簽了怎么辦?

不能上架到App Store的iOS應用 &#xff0c;幾乎每一個開發者的選擇都是通過iOS簽名這種內測渠道來完成APP的上架任務&#xff0c;最常用的就是企業簽名、超級簽名以及TF上架&#xff0c;其中最受歡迎的當屬于企業簽名了。不過企業簽名會出現掉簽的現象&#xff0c;那么企業簽名…

存儲成本深度優化:冷熱分層與生命周期管理——從視頻平臺年省200萬實踐解析智能存儲架構

一、冷熱分層&#xff1a;存儲成本優化的核心邏輯1.1 數據訪問的“二八定律”據行業統計&#xff0c;80%的訪問集中在20%的熱數據上&#xff0c;而超過90天的歷史數據訪問頻率下降70%以上。某視頻平臺存儲超10PB媒體文件&#xff0c;未分層前年存儲成本高達680萬元&#xff0c;…

Java設計模式之《備忘錄模式》

目錄 1. 概念 1.1、定義 1.2、適用場景 2、角色劃分 3、實現 1、Originator&#xff08;發起人&#xff09; 2、Memento&#xff08;備忘錄&#xff09; 3、Caretaker&#xff08;管理者&#xff09; 4、使用示例 4、優缺點 4.1、優點 4.2、缺點 前言 備忘錄模式是…

SpringBoot 多環境配置

在實際項目開發中&#xff0c;不同環境往往有不同的配置需求&#xff1a; 開發環境&#xff08;dev&#xff09;&#xff1a;本地調試&#xff0c;連接測試數據庫&#xff1b;測試環境&#xff08;test&#xff09;&#xff1a;接口聯調&#xff0c;接近真實場景&#xff1b;生…

延凡智慧醫院數字孿生平臺

延凡智慧醫院數字孿生平臺是延凡科技依托物聯網、數字孿生、AI 算法及邊緣計算技術打造的醫療場景全要素數字化解決方案&#xff0c;通過構建醫院物理實體與虛擬空間的實時映射&#xff0c;實現醫療資源優化、運營效率提升及患者體驗升級。一、平臺價值&#xff08;一&#xff…

談談WebAssembly、PWA、Web Workers的作用和場景

WebAssembly、PWA 和 Web Workers 是現代 Web 開發中提升性能、擴展能力的重要技術&#xff0c;各自解決不同場景的問題&#xff0c;以下結合實際使用經驗分析&#xff1a;一、WebAssembly&#xff08;Wasm&#xff09;&#xff1a;高性能代碼執行作用&#xff1a;WebAssembly …

嵌入式第十八課!!數據結構篇入門及單向鏈表

在前幾章對C語言的學習中&#xff0c;我們學到了&#xff1a;基本的C語法和簡單算法面向過程的編程思想而在數據結構這一篇章&#xff0c;我們將要學習&#xff1a;常用的數據存儲結構算法面向對象的編程思想數據結構在正式開始學習之前&#xff0c;我們先來了解一下什么是數據…

win10任務欄出問題了,原來是wincompressbar導致的

問題描述兄弟們客戶說自己電腦現在有問題了&#xff0c;任務欄顯示的都不對&#xff0c;和之前的都不一樣&#xff0c;現在使用起來非常難受&#xff0c;我們來看一下&#xff0c;這到底是什么問題吧&#xff01;到客戶現場&#xff0c;查看發現&#xff0c;客戶桌面系統最底下…

FFmpegHandler 功能解析,C語言程序化設計與C++面向對象設計的核心差異

FFmpegHandler 功能解析 本文件記錄了關于 FFmpegHandler 類中核心函數工作流程的詳細解釋。Q: FFmpeg逐幀解碼&#xff0c;FFmpegHandler::openVideo 和 FFmpegHandler::readAVFrame 這兩個函數都分別做了什么&#xff1f; A: 可以把整個過程想象成“準備播放一部電影”&#…