MyBatis-Plus增刪改查的通用化封裝過程
要實現(xiàn) MyBatis-Plus 增刪改查的通用化封裝,核心思路是利用泛型 + 繼承封裝通用的 Mapper、Service、Controller 層,讓業(yè)務(wù)模塊直接繼承這些通用類,無需重復(fù)編寫增刪改查代碼。
以下是完整的實現(xiàn)方案(Spring Boot 環(huán)境):
一、基礎(chǔ)準備:統(tǒng)一響應(yīng)結(jié)果
先封裝通用響應(yīng)類,保證接口返回格式統(tǒng)一,減少重復(fù)編碼:
package com.example.mpdemo.common;
import lombok.Data;
/**
* 通用響應(yīng)結(jié)果類
* @param <T> 響應(yīng)數(shù)據(jù)類型
*/
@Data
public class Result<T> {
// 響應(yīng)碼(200成功,500失?。?
private Integer code;
// 響應(yīng)消息
private String msg;
// 響應(yīng)數(shù)據(jù)
private T data;
// 成功響應(yīng)(無數(shù)據(jù))
public static <T> Result<T> success() {
return new Result<>(200, "操作成功", null);
}
// 成功響應(yīng)(有數(shù)據(jù))
public static <T> Result<T> success(T data) {
return new Result<>(200, "操作成功", data);
}
// 失敗響應(yīng)
public static <T> Result<T> fail(String msg) {
return new Result<>(500, msg, null);
}
}
二、通用層封裝
1. 通用 Mapper 層(BaseMapper 增強)
MyBatis-Plus 的 BaseMapper 已封裝基礎(chǔ) CRUD,我們只需定義通用接口讓業(yè)務(wù) Mapper 繼承:
package com.example.mpdemo.mapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
/**
* 通用 Mapper 接口
* @param <T> 實體類類型
*/
@Mapper
public interface BaseGenericMapper<T> extends BaseMapper<T> {
// 無需額外方法,繼承 BaseMapper 的 17 個基礎(chǔ) CRUD 方法即可
}
2. 通用 Service 層
封裝通用 Service 接口和實現(xiàn)類,復(fù)用 IService 的高級 CRUD 能力:
(1)通用 Service 接口
package com.example.mpdemo.service;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.IService;
import java.io.Serializable;
import java.util.List;
/**
* 通用 Service 接口
* @param <T> 實體類類型
*/
public interface BaseGenericService<T> extends IService<T> {
// 可擴展通用方法,比如自定義分頁、批量操作等
List<T> list(Wrapper<T> queryWrapper); // 條件查詢列表
IPage<T> page(IPage<T> page, Wrapper<T> queryWrapper); // 條件分頁查詢
T getById(Serializable id); // 根據(jù) ID 查詢
boolean saveEntity(T entity); // 新增
boolean updateEntity(T entity); // 修改
boolean removeById(Serializable id); // 根據(jù) ID 刪除
}
(2)通用 Service 實現(xiàn)類
package com.example.mpdemo.service.impl;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.mpdemo.mapper.BaseGenericMapper;
import com.example.mpdemo.service.BaseGenericService;
import java.io.Serializable;
import java.util.List;
/**
* 通用 Service 實現(xiàn)類
* @param <M> Mapper 類型
* @param <T> 實體類類型
*/
public class BaseGenericServiceImpl<M extends BaseGenericMapper<T>, T>
extends ServiceImpl<M, T> implements BaseGenericService<T> {
@Override
public List<T> list(Wrapper<T> queryWrapper) {
return baseMapper.selectList(queryWrapper);
}
@Override
public IPage<T> page(IPage<T> page, Wrapper<T> queryWrapper) {
return baseMapper.selectPage(page, queryWrapper);
}
@Override
public T getById(Serializable id) {
return baseMapper.selectById(id);
}
@Override
public boolean saveEntity(T entity) {
return save(entity); // 復(fù)用 IService 的 save 方法
}
@Override
public boolean updateEntity(T entity) {
return updateById(entity); // 復(fù)用 IService 的 updateById 方法
}
@Override
public boolean removeById(Serializable id) {
return baseMapper.deleteById(id);
}
}
3. 通用 Controller 層(核心)
封裝通用的增刪改查接口,業(yè)務(wù) Controller 只需繼承此類并指定實體和主鍵類型,無需重復(fù)編寫接口:
package com.example.mpdemo.controller;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.mpdemo.common.Result;
import com.example.mpdemo.service.BaseGenericService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import java.io.Serializable;
import java.util.List;
/**
* 通用 CRUD Controller
* @param <T> 實體類類型
* @param <K> 主鍵類型(如 Long、String)
*/
public class BaseGenericController<T, K extends Serializable> {
// 注入通用 Service(由子類指定具體實現(xiàn))
@Autowired
protected BaseGenericService<T> baseService;
/**
* 1. 新增
*/
@PostMapping
public Result<T> add(@RequestBody T entity) {
boolean success = baseService.saveEntity(entity);
return success ? Result.success(entity) : Result.fail("新增失敗");
}
/**
* 2. 根據(jù) ID 刪除
*/
@DeleteMapping("/{id}")
public Result<Void> delete(@PathVariable K id) {
boolean success = baseService.removeById(id);
return success ? Result.success() : Result.fail("刪除失敗");
}
/**
* 3. 修改
*/
@PutMapping
public Result<T> update(@RequestBody T entity) {
boolean success = baseService.updateEntity(entity);
return success ? Result.success(entity) : Result.fail("修改失敗");
}
/**
* 4. 根據(jù) ID 查詢
*/
@GetMapping("/{id}")
public Result<T> getById(@PathVariable K id) {
T entity = baseService.getById(id);
return entity != null ? Result.success(entity) : Result.fail("數(shù)據(jù)不存在");
}
/**
* 5. 查詢所有(無條件)
*/
@GetMapping("/list")
public Result<List<T>> list() {
List<T> list = baseService.list(Wrappers.emptyWrapper());
return Result.success(list);
}
/**
* 6. 分頁查詢(默認第1頁,每頁10條,可傳參數(shù)自定義)
*/
@GetMapping("/page")
public Result<IPage<T>> page(
@RequestParam(defaultValue = "1") Long current,
@RequestParam(defaultValue = "10") Long size) {
IPage<T> page = baseService.page(new Page<>(current, size), Wrappers.emptyWrapper());
return Result.success(page);
}
}
三、業(yè)務(wù)模塊使用示例(以 User 為例)
只需編寫少量代碼,繼承通用類即可擁有完整的增刪改查接口:
1. 實體類(User)
沿用之前的 User 實體(無需修改):
package com.example.mpdemo.entity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.Data;
import java.time.LocalDateTime;
@Data
@TableName("user")
public class User {
@TableId(type = IdType.ASSIGN_ID)
private Long id;
private String username;
private Integer age;
private String email;
private LocalDateTime createTime;
}
2. 業(yè)務(wù) Mapper(UserMapper)
繼承通用 Mapper:
package com.example.mpdemo.mapper;
import com.example.mpdemo.entity.User;
import org.springframework.stereotype.Repository;
@Repository
public interface UserMapper extends BaseGenericMapper<User> {
// 無需編寫任何代碼,自動擁有所有基礎(chǔ) CRUD 能力
}
3. 業(yè)務(wù) Service
(1)Service 接口
package com.example.mpdemo.service;
import com.example.mpdemo.entity.User;
public interface UserService extends BaseGenericService<User> {
// 可擴展自定義業(yè)務(wù)方法
}
(2)Service 實現(xiàn)類
package com.example.mpdemo.service.impl;
import com.example.mpdemo.entity.User;
import com.example.mpdemo.mapper.UserMapper;
import com.example.mpdemo.service.UserService;
import org.springframework.stereotype.Service;
@Service
public class UserServiceImpl extends BaseGenericServiceImpl<UserMapper, User> implements UserService {
// 無需編寫任何代碼,自動繼承通用 Service 的所有方法
}
4. 業(yè)務(wù) Controller
繼承通用 Controller,指定實體(User)和主鍵類型(Long):
package com.example.mpdemo.controller;
import com.example.mpdemo.entity.User;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
/**
* 用戶控制器,繼承通用 Controller 后自動擁有所有 CRUD 接口
*/
@RestController
@RequestMapping("/user")
public class UserController extends BaseGenericController<User, Long> {
// 無需編寫任何接口代碼,自動擁有:
// POST /user → 新增
// DELETE /user/{id} → 刪除
// PUT /user → 修改
// GET /user/{id} → 根據(jù)ID查詢
// GET /user/list → 查詢所有
// GET /user/page → 分頁查詢
}
四、接口測試(Postman/Curl)
| 接口 | 請求方式 | 說明 | 示例請求參數(shù) |
|---|---|---|---|
| /user | POST | 新增用戶 | {"username":"張三","age":20,"email":"zhangsan@example.com","createTime":"2026-03-13 10:00:00"} |
| /user/1 | DELETE | 刪除用戶 | 路徑參數(shù) id=1 |
| /user | PUT | 修改用戶 | {"id":1,"username":"張三","age":21} |
| /user/1 | GET | 查詢單個用戶 | 路徑參數(shù) id=1 |
| /user/list | GET | 查詢所有用戶 | 無參數(shù) |
| /user/page?current=1&size=2 | GET | 分頁查詢 | 參數(shù) current=1(頁碼)、size=2(每頁條數(shù)) |
五、擴展說明
- 自定義條件查詢:若需添加條件查詢,可在通用 Controller 中擴展,或在業(yè)務(wù) Controller 中新增方法:
// UserController 中新增條件查詢接口
@GetMapping("/listByAge")
public Result<List<User>> listByAge(@RequestParam Integer age) {
LambdaQueryWrapper<User> wrapper = Wrappers.lambdaQuery(User.class)
.gt(User::getAge, age);
List<User> list = baseService.list(wrapper);
return Result.success(list);
}
- 異常處理:可添加全局異常處理器(
@RestControllerAdvice),統(tǒng)一捕獲增刪改查中的異常(如主鍵不存在、參數(shù)非法等); - 權(quán)限控制:若需接口權(quán)限,可在通用 Controller 或業(yè)務(wù) Controller 中添加
@PreAuthorize等注解; - 參數(shù)校驗:可在實體類中添加
@NotNull、@NotBlank等校驗注解,配合@Valid實現(xiàn)參數(shù)校驗。
總結(jié)
- 核心思路:通過泛型 + 繼承封裝通用的 Mapper、Service、Controller,業(yè)務(wù)模塊只需繼承通用類,無需重復(fù)編寫增刪改查代碼;
- 復(fù)用性:通用層封裝了 6 個核心 CRUD 接口(新增、刪除、修改、單查、列表、分頁),覆蓋 90% 以上的單表業(yè)務(wù)場景;
- 擴展性:通用類預(yù)留了擴展接口,業(yè)務(wù)模塊可按需新增自定義方法,不破壞通用邏輯。
這種方式極大減少了重復(fù)編碼,符合“開閉原則”,是企業(yè)開發(fā)中常用的 MyBatis-Plus 最佳實踐。
以上為個人經(jīng)驗,希望能給大家一個參考,也希望大家多多支持腳本之家。
相關(guān)文章
SpringCloud超詳細講解微服務(wù)網(wǎng)關(guān)Zuul基礎(chǔ)
這篇文章主要介紹了SpringCloud?Zuul微服務(wù)網(wǎng)關(guān),負載均衡,熔斷和限流,本文給大家介紹的非常詳細,對大家的學(xué)習或工作具有一定的參考借鑒價值,需要的朋友可以參考下2022-10-10
java實現(xiàn)騰訊ocr圖片識別接口調(diào)用
這篇文章主要為大家詳細介紹了java實現(xiàn)騰訊ocr圖片識別接口調(diào)用,拍車牌識別車牌號功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下2018-11-11
SpringBoot配置主從數(shù)據(jù)庫實現(xiàn)讀寫分離
現(xiàn)在的 Web 應(yīng)用大都是讀多寫少,本文主要介紹了SpringBoot配置主從數(shù)據(jù)庫實現(xiàn)讀寫分離,具有一定的參考價值,感興趣的可以了解一下2023-11-11
在 Spring Boot 項目中實現(xiàn)文件下載功能
這篇文章主要介紹了在 Spring Boot 項目中實現(xiàn)文件下載功能,本文給大家介紹的非常詳細,具有一定的參考借鑒價值,需要的朋友可以參考下2019-09-09
Java數(shù)據(jù)結(jié)構(gòu)之鏈表的增刪查改詳解
今天帶大家來學(xué)習Java鏈表的增刪改查的相關(guān)知識,文中有非常詳細的代碼示例,對正在學(xué)習Java的小伙伴們有很好的幫助,需要的朋友可以參考下2021-05-05
分享Java8中通過Stream對列表進行去重的實現(xiàn)
本文主要介紹了分享Java8中通過Stream對列表進行去重的實現(xiàn),包括兩種方法,具有一定的參考價值,感興趣的可以了解一下2023-11-11

