目錄
- 一,簡介
-
- 1. 什么是mybatis-plus
- 2.mybatis-plus特點
- 二,搭建基本環境
-
- 1. 導入基本依賴:
- 2. 編寫配置文件
- 3. 創建實體類
- 4. 編寫controller層
- 5. 編寫service接口
- 6. 編寫service層
- 7. 編寫mapper層
- 三,基本知識介紹
-
- 1. 基本注解
-
- @TableName
- @TableId
- @TableFiled
- @TableLogic
- @Version
- @Transient
- 2. Wrapper的介紹*
-
- QueryWrapper
- UpdateWrapper
- LambdaQueryWrapper
- LambdaUpdateWrapper
- Wrappers
- 3. 分頁查詢
-
- 1. 配置相應的攔截器
- 2. 實現分頁邏輯
- 四,結語
一,簡介
1. 什么是mybatis-plus
MyBatis-Plus(簡稱MP)是一個MyBatis的增強工具,旨在在MyBatis的基礎上只做增強不做改變,以簡化開發、提高效率。MyBatis-Plus保持了MyBatis原有的所有特性,同時增加了一些實用的功能,使得開發者能夠更加便捷地進行數據庫操作。以下是MyBatis-Plus的一些主要特點和功能:
2.mybatis-plus特點
- 無侵入:引入MyBatis-Plus不會對現有的MyBatis工程產生影響,可以無縫集成到現有的項目中。
損耗小:啟動時自動注入基本的CRUD操作,幾乎不消耗額外的性能,可以直接面向對象操作數據庫。 - 強大的CRUD操作:內置通用Mapper、通用Service,通過少量配置即可實現單表的大部分CRUD操作。同時,MyBatis-Plus提供了強大的條件構造器,滿足復雜的查詢需求。
- 支持Lambda形式調用:利用Lambda表達式方便地編寫查詢條件,避免了字段名稱錯誤的問題。
- 支持主鍵自動生成:提供了多種主鍵生成策略,包括分布式唯一ID生成器,解決了主鍵問題。
- 支持ActiveRecord模式:通過繼承特定的基類,可以像操作對象一樣操作數據庫。
- 支持自定義全局通用操作:允許開發者注入自己的通用方法。
- 內置分頁插件:基于MyBatis的物理分頁,開發者可以輕松實現分頁查詢。
- 支持多種數據庫:兼容MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、PostgreSQL、SQL Server等多種數據庫。
- 內置性能分析插件:可以輸出SQL語句及其執行時間,有助于快速定位慢查詢。
- 內置全局攔截插件:提供全表刪除、更新操作的智能分析阻斷,防止誤操作。
二,搭建基本環境
1. 導入基本依賴:
<!--mybatis-plus依賴--><dependency><groupId>com.baomidou</groupId><artifactId>mybatis-plus-boot-starter</artifactId><version>3.5.7</version></dependency><!--mysql連接依賴--><dependency><groupId>mysql</groupId><artifactId>mysql-connector-java</artifactId><version>8.0.33</version></dependency><!--連接池依賴--><dependency><groupId>com.alibaba</groupId><artifactId>druid-spring-boot-starter</artifactId><version>1.1.18</version></dependency>
2. 編寫配置文件
spring:data:datasource:driver-class-name: com.mysql.cj.jdbc.Driverurl: jdbc:mysql://localhost:3306/mybatis_study?serverTimezone=Asia/Shanghai&useUnicode=true&characterEncoding=utf-8&useSSL=falseusername: rootpassword: roottype: com.alibaba.druid.pool.DruidDataSource
3. 創建實體類
package org.example.pojo;import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;import java.util.Date;
@TableName("student")
public class Student {@TableId(type = IdType.AUTO)private int id;private String studentNumber;private String name;private int gender; // 0 表示女性,1 表示男性private Date dateOfBirth;// Getters and Setters}
4. 編寫controller層
package org.example.controller;import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
@RequestMapping("/students")
public class StudentController {}
5. 編寫service接口
package org.example.service;import com.baomidou.mybatisplus.extension.service.IService;
import org.example.pojo.Student;public interface StudentService extends IService<Student> {
}
6. 編寫service層
package org.example.service.serviceImpl;import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.example.mapper.StudentMapper;
import org.example.pojo.Student;
import org.example.service.StudentService;
import org.springframework.stereotype.Service;@Service
public class StudentServiceImpl extends ServiceImpl<StudentMapper, Student> implements StudentService {}
7. 編寫mapper層
package org.example.mapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Mapper;
import org.example.pojo.Student;@Mapper
public interface StudentMapper extends BaseMapper<Student> {
}
三,基本知識介紹
1. 基本注解
@TableName
主要用于指定表名,實現實體類與表名的綁定,作用于類上,適用于表名與實體類名稱不統一的情況,統一的情況可以不用寫。
import com.baomidou.mybatisplus.annotation.TableName;
//此處表名稱為t_user,實體類名稱為User不統一
@TableName("t_user")
public class User {private Long id;private String name;private Integer age;private String email;// Getters and Setters
}
如果所有的表結構與實體類只是多了一個前綴,可以直接在配置文件里面配置全局的前綴,就可以不使用注解了,兩種方式都可以,根據具體場景選擇,配置如下:
mybatis-plus:global-config:db-config:table-prefix: t_
@TableId
作用于主鍵上,指明主鍵字段,并設置主鍵的生成方式。
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;@TableName("user_info") // 指定該實體類對應的數據表名
public class UserInfo {
//此處value也可以作用于映射,當實體類中
//的id字段名和數據庫中的字段名不相同時,可以使用其屬性做增強@TableId(value = "id", type = IdType.AUTO) // 標記為主鍵,并指定主鍵生成策略為自增private Long id;private String username;private String password;// Getters and Setterspublic Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}
}注解屬性:value:指定表中主鍵字段,多用于主鍵字段和實體類字段不同意type:id生成策略
對于IdType做出如下說明:
屬性
說明
適用場景
AUTO
數據庫自增主鍵
適用于 MySQL、SQL Server 等支持自增主鍵的數據庫
NONE
不使用任何主鍵生成策略
通常用于主鍵已經存在的情況
ASSIGN_ID
全局唯一ID(默認基于Snowflake算法生成)
適用于分布式系統,確保全局唯一性
ASSIGN_UUID
全局唯一UUID,生成32位的字符串
適用于需要字符串主鍵的場景
INPUT
自定義輸入主鍵值
適用于某些特殊場景,如導入數據時需要手動指定主鍵
@TableFiled
改注解作用眾多,多用于表字段和實體類字段名稱不統一,做映射處理,也可用于零時字段,不存入數據庫,或者是一些字段的填充處理(此處需要編寫填充處理器)。
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.FieldFill;
import com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler;import java.util.Date;@TableName("user_info")
public class UserInfo {@TableId(value = "id", type = IdType.AUTO)private Long id;@TableField("username")private String username;//此字段不參與查詢@TableField("password", select=false )private String password;@TableField("email")private String email;//注意,此處應該編寫相應的填充邏輯@TableField(value = "create_time", fill = FieldFill.INSERT)private Date createTime;@TableField(value = "update_time", fill = FieldFill.UPDATE)private Date updateTime;@TableField(exist = false)private String tempField; // 臨時字段,不在數據庫中// Getters and Setterspublic Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}public Date getCreateTime() {return createTime;}public void setCreateTime(Date createTime) {this.createTime = createTime;}public Date getUpdateTime() {return updateTime;}public void setUpdateTime(Date updateTime) {this.updateTime = updateTime;}public String getTempField() {return tempField;}public void setTempField(String tempField) {this.tempField = tempField;}
}屬性說明:value:同上面注解一樣,用于字段綁定,單個屬性的時候可以不寫select:在值為false的情況下用于設置不參查詢,查詢之后不會返回回來exist :用于類中的零時變量,數據庫中沒有該字段,只在java中使用fill:用于自動填充,比如create_time,update_time這一類,但需要編寫相應的處理器
對應處理器代碼:
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Component;import java.util.Date;@Component
public class MyMetaObjectHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {this.strictInsertFill(metaObject, "createTime", Date.class, new Date());this.strictInsertFill(metaObject, "updateTime", Date.class, new Date());}@Overridepublic void updateFill(MetaObject metaObject) {this.strictUpdateFill(metaObject, "updateTime", Date.class, new Date());}
}
@TableLogic
該字段用于指定邏輯刪除的字段,當執行刪除語句時,做更新操作,只改變當前字段的值,設置為刪除狀態,數據不做真實處理,查詢時也只查詢狀態為未刪除的數據(此過程不需要手動實現,mybatis-plus已經幫忙實現了,我們只需要添加字段,設置相應的狀態值)注:該字段也需要加入到對應的表里
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;@TableName("user_info")
public class UserInfo {@TableId(value = "id", type = IdType.AUTO)private Long id;private String username;private String password;private String email;@TableLogicprivate Integer isDeleted;// Getters and Setterspublic Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getUsername() {return username;}public void setUsername(String username) {this.username = username;}public String getPassword() {return password;}public void setPassword(String password) {this.password = password;}public String getEmail() {return email;}public void setEmail(String email) {this.email = email;}public Integer getIsDeleted() {return isDeleted;}public void setIsDeleted(Integer isDeleted) {this.isDeleted = isDeleted;}
}
在配置文件中添加如下配置:
mybatis-plus:global-config:db-config:# 邏輯刪除字段名logic-delete-field: deleted# 邏輯刪除字面值:未刪除為0logic-not-delete-value: 0# 邏輯刪除字面值:刪除為1logic-delete-value: 1
@Version
用于配置樂觀鎖字段,配置之后的更新操作都會先去比較版本,然后在去操作,整體采用cas機制實現。注:該字段也需要加入到對應的表里
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableLogic;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.Version;@TableName("order_info")
public class OrderInfo {@TableId(value = "id", type = IdType.AUTO)private Long id;private String orderNo;private Double amount;@Versionprivate Integer version;// Getters and Setterspublic Long getId() {return id;}public void setId(Long id) {this.id = id;}public String getOrderNo() {return orderNo;}public void setOrderNo(String orderNo) {this.orderNo = orderNo;}public Double getAmount() {return amount;}public void setAmount(Double amount) {this.amount = amount;}public Integer getVersion() {return version;}public void setVersion(Integer version) {this.version = version;}
}
此處需加相關的攔截器:
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.OptimisticLockerInnerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class MyBatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());return interceptor;}
}樂觀鎖的作用:樂觀鎖假設在并發環境中沖突較少,因此在操作數據時不立即獲取鎖,而是等到提交更新時才檢查是否有其他事務修改過數據。如果發現數據已被修改,則更新失敗,通常會拋出異常。特點:在提交更新時檢查版本號,如果版本號匹配則更新成功,否則更新失敗。效果:多個事務可以同時讀取和處理數據,但在提交更新時會檢查版本號,確保數據的一致性。
@Transient
作用于實體類字段,使其不參與數據庫的操作,其中包括(Insert,Update,Select),@TableField(exist=false)作用相同,充當零時變量。
@TableName("user")
public class User {@TableId(type = IdType.AUTO)private Long id;private String name;@Transientprivate String tempField;// getters and setters
}
2. Wrapper的介紹*
概念:MyBatisPlus提供了QueryWrapper、LambdaQueryWrapper、UpdateWrapper和LambdaUpdateWrapper等條件類,大大簡化了我們的開發,可以使代碼更加清晰和易于管理,其中包括多條件查詢、排序、條件優先級以及有條件時才加入條件的場景,并提供了示例代碼展示如何進行數據庫查詢和更新操作。
大致的條件(此處粗略列舉):
方法
描述
eq
等于
ne
不等于
gt
大于
ge
大于等于
lt
小于
le
小于等于
like
模糊查詢
notLike
反向模糊查詢
in
在某集合內
notIn
不在某集合內
isNull
為空
isNotNull
不為空
between
在某個區間內
notBetween
不在某個區間內
set
設置字段值
QueryWrapper
作用于查詢設置查詢條件。
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;public class UserService {private UserMapper userMapper;public List<User> getUsersByConditions() {// 創建 QueryWrapper 對象QueryWrapper<User> queryWrapper = new QueryWrapper<>();// 添加查詢條件queryWrapper.eq("name", "張三").ge("age", 18).orderByDesc("create_time");// 執行查詢return userMapper.selectList(queryWrapper);}
}
此處執行的sql語句:
SELECT * FROM user WHERE name = '張三' AND age >= 18 ORDER BY create_time DESC;
UpdateWrapper
作用于更新設置條件。
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;public class UserService {private UserMapper userMapper;public int updateUserById() {// 創建 UpdateWrapper 對象UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();// 添加更新條件updateWrapper.eq("id", 1);// 創建要更新的對象User user = new User();user.setName("李四");// 執行更新return userMapper.update(user, updateWrapper);}
}
此處執行的sql語句:
UPDATE user SET name = '李四' WHERE id = 1;
LambdaQueryWrapper
在QueryWrapper做了增強,作用一樣,用于設置查詢條件。
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;public class UserService {private UserMapper userMapper;public List<User> getUsersByLambdaConditions() {// 創建 LambdaQueryWrapper 對象LambdaQueryWrapper<User> lambdaQueryWrapper = new LambdaQueryWrapper<>();// 添加查詢條件lambdaQueryWrapper.eq(User::getName, "張三").ge(User::getAge, 18).orderByDesc(User::getCreateTime);// 執行查詢return userMapper.selectList(lambdaQueryWrapper);}
}
此處執行的sql語句:
SELECT * FROM user WHERE name = '張三' AND age >= 18 ORDER BY create_time DESC;
LambdaUpdateWrapper
在UpdateWrapper做了增強,作用一樣,用于設置跟新條件。
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;public class UserService {private UserMapper userMapper;public int updateUserByIdWithLambda() {// 創建 LambdaUpdateWrapper 對象LambdaUpdateWrapper<User> lambdaUpdateWrapper = new LambdaUpdateWrapper<>();// 添加更新條件lambdaUpdateWrapper.eq(User::getId, 1);// 創建要更新的對象User user = new User();user.setName("李四");// 執行更新return userMapper.update(user, lambdaUpdateWrapper);}
}
此處執行的sql語句:
UPDATE user SET name = '李四' WHERE id = 1;
Wrappers
用于更簡便的條件設置
import com.baomidou.mybatisplus.core.toolkit.Wrappers;public class UserService {private UserMapper userMapper;public List<User> getUsersByConditionsUsingWrappers() {// 創建 QueryWrapper 對象QueryWrapper<User> queryWrapper = Wrappers.<User>query().eq("name", "張三").ge("age", 18).orderByDesc("create_time");// 執行查詢return userMapper.selectList(queryWrapper);}
}
此處執行的sql語句:
SELECT * FROM user WHERE name = '張三' AND age >= 18 ORDER BY create_time DESC;
3. 分頁查詢
1. 配置相應的攔截器
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;@Configuration
public class MyBatisPlusConfig {@Beanpublic MybatisPlusInterceptor mybatisPlusInterceptor() {MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();interceptor.addInnerInterceptor(new PaginationInnerInterceptor());return interceptor;}
}
2. 實現分頁邏輯
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.example.entity.User;
import com.example.mapper.UserMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class UserService {@Autowiredprivate UserMapper userMapper;public IPage<User> getUserPage(int current, int size) {// 創建 Page 對象,傳入當前頁碼和每頁大小Page<User> page = new Page<>(current, size);// 創建 QueryWrapper 對象,添加查詢條件QueryWrapper<User> queryWrapper = new QueryWrapper<>();queryWrapper.eq("status", 1).orderByDesc("create_time");// 執行分頁查詢IPage<User> userPage = userMapper.selectPage(page, queryWrapper);// 獲取分頁數據List<User> users = userPage.getRecords();// 獲取總記錄數long total = userPage.getTotal();// 獲取當前頁碼int current = userPage.getCurrent();// 獲取每頁大小int size = userPage.getSize();// 獲取總頁數int pages = userPage.getPages();return userPage;}
}
執行對應的sql語句是:
-- 分頁查詢
SELECT *
FROM user
WHERE status = 1
ORDER BY create_time DESC
LIMIT 0, 10; -- 當前頁碼為1,每頁大小為10
四,結語
在本文中,我們詳細介紹了 MyBatis-Plus 的核心功能和使用方法,包括如何配置分頁插件、編寫分頁查詢代碼、使用各種 Wrapper 構建復雜查詢條件等。通過這些內容,相信你已經對 MyBatis-Plus 有了更深入的了解,并能夠在實際項目中靈活應用這些功能。
MyBatis-Plus 作為一個強大的 MyBatis 增強工具,不僅簡化了數據訪問層的開發工作,還提供了許多便捷的功能,如分頁查詢、鏈式編程、樂觀鎖等。它能夠顯著提升開發效率,減少重復代碼,使你的項目更加簡潔和高效。
如果你在閱讀本文后對 MyBatis-Plus 感興趣,不妨在自己的項目中嘗試一下。實踐是最好的老師,通過實際操作,你會更加深刻地理解這些功能的奧妙。同時,也歡迎你在評論區分享你的使用經驗和遇到的問題,我們一起探討和解決。
最后,感謝你花時間閱讀本文,希望本文能為你帶來幫助。如果你覺得本文對你有幫助,別忘了點贊和分享,讓更多的人受益。讓我們一起在技術的道路上不斷前行,共同成長!