Mybatis_plus基礎(chǔ)教程(總結(jié)篇)
一.簡(jiǎn)介
官網(wǎng)網(wǎng)址:http://mp.baomidou.com/
參考教程:http://mp.baomidou.com/guide/
二.特性
無侵入:只做增強(qiáng)不做改變,引入它不會(huì)對(duì)現(xiàn)有工程產(chǎn)生影響,如絲般順滑
損耗小:?jiǎn)?dòng)即會(huì)自動(dòng)注入基本 CURD,性能基本無損耗,直接面向?qū)ο蟛僮?br />
強(qiáng)大的 CRUD 操作:內(nèi)置通用 Mapper、通用 Service,僅僅通過少量配置即可實(shí)現(xiàn)單表大部分 CRUD 操作,更有強(qiáng)大的條件構(gòu)造器,滿足各類使用需求
支持 Lambda 形式調(diào)用:通過 Lambda 表達(dá)式,方便的編寫各類查詢條件,無需再擔(dān)心字段寫錯(cuò)
支持多種數(shù)據(jù)庫:支持 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer2005、SQLServer 等多種數(shù)據(jù)庫
支持主鍵自動(dòng)生成:支持多達(dá) 4 種主鍵策略(內(nèi)含分布式唯一 ID 生成器 - Sequence),可自由配置,完美解決主鍵問題
支持 XML 熱加載:Mapper 對(duì)應(yīng)的 XML 支持熱加載,對(duì)于簡(jiǎn)單的 CRUD 操作,甚至可以無 XML 啟動(dòng)
支持 ActiveRecord 模式:支持 ActiveRecord 形式調(diào)用,實(shí)體類只需繼承 Model 類即可進(jìn)行強(qiáng)大的 CRUD 操作
支持自定義全局通用操作:支持全局通用方法注入( Write once, use anywhere )
支持關(guān)鍵詞自動(dòng)轉(zhuǎn)義:支持?jǐn)?shù)據(jù)庫關(guān)鍵詞(order、key…)自動(dòng)轉(zhuǎn)義,還可自定義關(guān)鍵詞
內(nèi)置代碼生成器:采用代碼或者 Maven 插件可快速生成 Mapper 、 Model 、 Service 、 Controller 層代碼,支持模板引擎,更有超多自定義配置等您來使用
內(nèi)置分頁插件:基于 MyBatis 物理分頁,開發(fā)者無需關(guān)心具體操作,配置好插件之后,寫分頁等同于普通 List 查詢
內(nèi)置性能分析插件:可輸出 Sql 語句以及其執(zhí)行時(shí)間,建議開發(fā)測(cè)試時(shí)啟用該功能,能快速揪出慢查詢
內(nèi)置全局?jǐn)r截插件:提供全表 delete 、 update 操作智能分析阻斷,也可自定義攔截規(guī)則,預(yù)防誤操作
內(nèi)置 Sql 注入剝離器:支持 Sql 注入剝離,有效預(yù)防 Sql 注入攻擊
三.MyBatis_plus入門
①創(chuàng)建并初始化數(shù)據(jù)庫
mybatis_plus
②創(chuàng)建 User 表
其表結(jié)構(gòu)如下:

其對(duì)應(yīng)的數(shù)據(jù)庫 Schema 腳本如下:
DROP TABLE IF EXISTS user; CREATE TABLE user ( id BIGINT(20) NOT NULL COMMENT '主鍵ID', name VARCHAR(30) NULL DEFAULT NULL COMMENT '姓名', age INT(11) NULL DEFAULT NULL COMMENT '年齡', email VARCHAR(50) NULL DEFAULT NULL COMMENT '郵箱', PRIMARY KEY (id) );
其對(duì)應(yīng)的數(shù)據(jù)庫 Data 腳本如下:
DELETE FROM user; INSERT INTO user (id, name, age, email) VALUES (1, 'Jone', 18, 'test1@baomidou.com'), (2, 'Jack', 20, 'test2@baomidou.com'), (3, 'Tom', 28, 'test3@baomidou.com'), (4, 'Sandy', 21, 'test4@baomidou.com'), (5, 'Billie', 24, 'test5@baomidou.com');
四.初始化工程
使用 Spring Initializr 快速初始化一個(gè) Spring Boot 工程
Group:com.atguigu
Artifact:mybatis-plus
版本:2.2.1.RELEASE
五.添加依賴
①引入依賴
spring-boot-starter、spring-boot-starter-test
添加:mybatis-plus-boot-starter、MySQL、lombok、
在項(xiàng)目中使用Lombok可以減少很多重復(fù)代碼的書寫。比如說getter/setter/toString等方法的編寫
<dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> <exclusions> <exclusion> <groupId>org.junit.vintage</groupId> <artifactId>junit-vintage-engine</artifactId> </exclusion> </exclusions> </dependency> <!--mybatis-plus--> <dependency> <groupId>com.baomidou</groupId> <artifactId>mybatis-plus-boot-starter</artifactId> <version>3.0.5</version> </dependency> <!--mysql--> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> </dependency> <!--lombok用來簡(jiǎn)化實(shí)體類--> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> </dependency> </dependencies>
注意:引入 MyBatis-Plus 之后請(qǐng)不要再次引入 MyBatis 以及 MyBatis-Spring,以避免因版本差異導(dǎo)致的問題。
②idea中安裝lombok插件
1).idea2020版本

六.配置
在 application.properties 配置文件中添加 MySQL 數(shù)據(jù)庫的相關(guān)配置:
mysql5:
#mysql數(shù)據(jù)庫連接 spring.datasource.driver-class-name=com.mysql.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus spring.datasource.username=root spring.datasource.password=123456
mysql8以上(spring boot 2.1):
注意:driver和url的變化
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver spring.datasource.url=jdbc:mysql://localhost:3306/mybatis_plus?serverTimezone=GMT%2B8&useUnicode=true&characterEncoding=UTF-8 spring.datasource.username=root spring.datasource.password=123456
注意:
1、這里的 url 使用了 ?serverTimezone=GMT%2B8 后綴,因?yàn)镾pring Boot 2.1 集成了 8.0版本的jdbc驅(qū)動(dòng),這個(gè)版本的 jdbc 驅(qū)動(dòng)需要添加這個(gè)后綴,否則運(yùn)行測(cè)試用例報(bào)告如下錯(cuò)誤:
java.sql.SQLException: The server time zone value ‘Öйú±ê׼ʱ¼ä' is unrecognized or represents more
2、這里的 driver-class-name 使用了 com.mysql.cj.jdbc.Driver ,在 jdbc 8 中 建議使用這個(gè)驅(qū)動(dòng),之前的 com.mysql.jdbc.Driver 已經(jīng)被廢棄,否則運(yùn)行測(cè)試用例的時(shí)候會(huì)有 WARN 信息
七.編寫代碼
①主類
在 Spring Boot 啟動(dòng)類中添加 @MapperScan 注解,掃描 Mapper 文件夾
注意:掃描的包名根據(jù)實(shí)際情況修改
@SpringBootApplication
@MapperScan("com.mybatisplus.mapper")
public class MybatisPlusApplication {
......
}
②實(shí)體
創(chuàng)建包 entity 編寫實(shí)體類 User.java(此處使用了 Lombok 簡(jiǎn)化代碼)
//@Data:該注解使用在類上,該注解會(huì)提供getter、setter、equals、canEqual、hashCode、toString方法。
@Data
public class User {
private Long id;
private String name;
private Integer age;
private String email;
}
@Data:該注解使用在類上,該注解會(huì)提供getter、setter、equals、canEqual、hashCode、toString方法。
Lombok使用參考:https://blog.csdn.net/motui/article/details/79012846
③mapper
創(chuàng)建包 mapper 編寫Mapper 接口: UserMapper.java
public interface UserMapper extends BaseMapper<User> {
}
八.開始使用
添加測(cè)試類,進(jìn)行功能測(cè)試:
@SpringBootTest
public class MybatisPlusApplicationTests {
@Autowired
private UserMapper userMapper;
@Test
public void testSelectList() {
System.out.println(("----- selectAll method test ------"));
//UserMapper 中的 selectList() 方法的參數(shù)為 MP 內(nèi)置的條件封裝器 Wrapper
//所以不填寫就是無任何條件
List<User> users = userMapper.selectList(null);
users.forEach(System.out::println);
}
}
注意:
IDEA在 userMapper 處報(bào)錯(cuò),因?yàn)檎也坏阶⑷氲膶?duì)象,因?yàn)轭愂莿?dòng)態(tài)創(chuàng)建的,但是程序可以正確的執(zhí)行。
為了避免報(bào)錯(cuò),可以在 dao 層 的接口上添加----- @Repository 注
控制臺(tái)輸出:
User(id=1, name=Jone, age=18, email=test1@baomidou.com)
User(id=2, name=Jack, age=20, email=test2@baomidou.com)
User(id=3, name=Tom, age=28, email=test3@baomidou.com)
User(id=4, name=Sandy, age=21, email=test4@baomidou.com)
User(id=5, name=Billie, age=24, email=test5@baomidou.com)
通過以上幾個(gè)簡(jiǎn)單的步驟,我們就實(shí)現(xiàn)了 User 表的 CRUD 功能,甚至連 XML 文件都不用編寫!
九.配置日志
查看sql輸出日志:在application.properties中加:
#mybatis日志 mybatis-plus.configuration.log-impl=org.apache.ibatis.logging.stdout.StdOutImpl
在輸出臺(tái)中就有日志了

十.MyBatisPlus的CRUD 接口
1、主鍵策略
(1)ID_WORKER
MyBatis-Plus默認(rèn)的主鍵策略是:ID_WORKER 全局唯一ID
參考資料:分布式系統(tǒng)唯一ID生成方案匯總:https://www.cnblogs.com/haoxinyue/p/5208136.html
(2)自增策略
要想主鍵自增需要配置如下主鍵策略
①.需要在創(chuàng)建數(shù)據(jù)表的時(shí)候設(shè)置主鍵自增
實(shí)體字段中配置 @TableId(type = IdType.AUTO)
在User實(shí)體類中的id 上加
@TableId(type = IdType.AUTO) private Long id;
要想影響所有實(shí)體的配置,可以設(shè)置全局主鍵配置
#全局設(shè)置主鍵生成策略 mybatis-plus.global-config.db-config.id-type=auto
其它主鍵策略:分析 IdType 源碼可知
@Getter
public enum IdType {
/**
* 數(shù)據(jù)庫ID自增
*/
AUTO(0),
/**
* 該類型為未設(shè)置主鍵類型
*/
NONE(1),
/**
* 用戶輸入ID
* 該類型可以通過自己注冊(cè)自動(dòng)填充插件進(jìn)行填充
*/
INPUT(2),
/* 以下3種類型、只有當(dāng)插入對(duì)象ID 為空,才自動(dòng)填充。 */
/**
* 全局唯一ID (idWorker)
*/
ID_WORKER(3),
/**
* 全局唯一ID (UUID)
*/
UUID(4),
/**
* 字符串全局唯一ID (idWorker 的字符串表示)
*/
ID_WORKER_STR(5);
private int key;
IdType(int key) {
this.key = key;
}
}
2.插入操作
在User實(shí)體類中加
//@TableId:MyBatis-Plus默認(rèn)的主鍵策略是:ID_WORKER 全局唯一ID @TableId(type = IdType.ID_WORKER) private Long id;
在測(cè)試類中
public class MybatisPlusApplicationTests {
@Autowired
private UserMapper userMapper;
public void testInsert(){
User user = new User();
user.setName("Helen");
user.setAge(18);
user.setEmail("55317332@qq.com");
int result = userMapper.insert(user);
System.out.println(result); //影響的行數(shù)
System.out.println(user); //id自動(dòng)回填
}
注意:數(shù)據(jù)庫插入id值默認(rèn)為:全局唯一id

3.update
1、根據(jù)Id更新操作
**注意:**update時(shí)生成的sql自動(dòng)是動(dòng)態(tài)sql:UPDATE user SET age=? WHERE id=?
@Test
public void testUpdateById(){
User user = new User();
user.setId(1L);
user.setAge(28);
int result = userMapper.updateById(user);
System.out.println(result);
}
2、自動(dòng)填充
項(xiàng)目中經(jīng)常會(huì)遇到一些數(shù)據(jù),每次都使用相同的方式填充,例如記錄的創(chuàng)建時(shí)間,更新時(shí)間等。
我們可以使用MyBatis Plus的自動(dòng)填充功能,完成這些字段的賦值工作:
(1)數(shù)據(jù)庫表中添加自動(dòng)填充字段
在User表中添加datetime類型的新的字段 create_time、update_time
(2)實(shí)體上添加注解
@Data
public class User {
@TableId(type = IdType.ID_WORKER)
private Long id;
private String name;
private Integer age;
private String email;
//在數(shù)據(jù)庫中是create_time 在User實(shí)體類中是createTime, _t自動(dòng)轉(zhuǎn)換T
@TableField( fill=FieldFill.INSERT)
private Date createTime;
@TableField(fill = FieldFill.INSERT_UPDATE)
private Date updateTime;
}
(3)實(shí)現(xiàn)元對(duì)象處理器接口
注意:不要忘記添加 @Component 注解
package com.handler;
import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;
import org.apache.ibatis.reflection.MetaObject;
import org.springframework.stereotype.Controller;
import java.util.Date;
@Component
public class MyMetaObjectHandler implements MetaObjectHandler {
/**
* 插入時(shí)時(shí)間
* @param metaObject
*/
@Override
public void insertFill(MetaObject metaObject) {
this.setFieldValByName("createTime",new Date(),metaObject);
this.setFieldValByName("updateTime",new Date(),metaObject);
}
/**
* 修改時(shí)時(shí)間
* @param metaObject
*/
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updateTime",new Date(),metaObject);
}
}
(4)再次運(yùn)行 測(cè)試 結(jié)果

4.樂觀鎖
**主要適用場(chǎng)景:**當(dāng)要更新一條記錄的時(shí)候,希望這條記錄沒有被別人更新,也就是說實(shí)現(xiàn)線程安全的數(shù)據(jù)更新
樂觀鎖實(shí)現(xiàn)方式:
①取出記錄時(shí),獲取當(dāng)前version
②更新時(shí),帶上這個(gè)version
③執(zhí)行更新時(shí), set version = newVersion where version = oldVersion
④如果version不對(duì),就更新失敗
(1)數(shù)據(jù)庫中添加version字段`在這里插入代碼片
ALTER TABLE `user` ADD COLUMN `version` INT

(2)實(shí)體類添加version字段 :并添加 @Version 注解
@TableField(fill = FieldFill.INSERT) 3 private Integer version;

(3)元對(duì)象處理器接口添加version的insert默認(rèn)值
@Controller
public class MyMetaObjectHandler implements MetaObjectHandler {
/**
* 插入時(shí)時(shí)間
* @param metaObject
*/
@Override
public void insertFill(MetaObject metaObject) {
this.setFieldValByName("createTime",new Date(),metaObject);
this.setFieldValByName("updateTime",new Date(),metaObject);
//看這里
this.setFieldValByName("version",1,metaObject);
}
/**
* 修改時(shí)時(shí)間
* @param metaObject
*/
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updateTime",new Date(),metaObject);
}
}
特別說明:
支持的數(shù)據(jù)類型只有 int,Integer,long,Long,Date,Timestamp,LocalDateTime
整數(shù)類型下 newVersion = oldVersion + 1
newVersion 會(huì)回寫到 entity 中
僅支持 updateById(id) 與 update(entity, wrapper) 方法
在 update(entity, wrapper) 方法下, wrapper 不能復(fù)用!!!
(4)在 MybatisPlusConfig 中注冊(cè) Bean
創(chuàng)建配置類
package com.config;
import com.baomidou.mybatisplus.core.injector.ISqlInjector;
import com.baomidou.mybatisplus.extension.injector.LogicSqlInjector;
import com.baomidou.mybatisplus.extension.plugins.OptimisticLockerInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PaginationInterceptor;
import com.baomidou.mybatisplus.extension.plugins.PerformanceInterceptor;
import org.mybatis.spring.annotation.MapperScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Profile;
import org.springframework.stereotype.Controller;
@Configuration
@MapperScan("com.mapper")
public class MyConfig {
/**
* 樂觀鎖插件
*/
@Bean
public OptimisticLockerInterceptor optimisticLockerInterceptor() {
return new OptimisticLockerInterceptor();
}
}
(5)測(cè)試樂觀鎖可以修改成功
測(cè)試后分析打印的sql語句,將version的數(shù)值進(jìn)行了加1操作
/**
* 測(cè)試 樂觀鎖插件
*/
@Test
public void testOptimisticLocker() {
//查詢
User user = userMapper.selectById(1L);
//修改數(shù)據(jù)
user.setName("Helen Yao");
user.setEmail("helen@qq.com");
//執(zhí)行更新
userMapper.updateById(user);
}
(5)測(cè)試樂觀鎖修改失敗
/**
* 測(cè)試樂觀鎖插件 失敗
*/
@Test
public void testOptimisticLockerFail() {
//查詢
User user = userMapper.selectById(1L);
//修改數(shù)據(jù)
user.setName("Helen Yao1");
user.setEmail("helen@qq.com1");
//模擬取出數(shù)據(jù)后,數(shù)據(jù)庫中version實(shí)際數(shù)據(jù)比取出的值大,即已被其它線程修改并更新了version
user.setVersion(user.getVersion() - 1);
//執(zhí)行更新
userMapper.updateById(user);
}
5.select
1、根據(jù)id查詢記錄
@Test
public void testSelectById(){
User user = userMapper.selectById(1L);
System.out.println(user);
}
2、通過多個(gè)id批量查詢
完成了動(dòng)態(tài)sql的foreach的功能
@Test
public void testSelectBatchIds(){
List<User> users = userMapper.selectBatchIds(Arrays.asList(1, 2, 3));
users.forEach(System.out::println);
}
3、簡(jiǎn)單的條件查詢
通過map封裝查詢條件(不怎么用 看看就行)
@Test
public void testSelectByMap(){
HashMap<String, Object> map = new HashMap<>();
map.put("name", "Helen");
map.put("age", 18);
List<User> users = userMapper.selectByMap(map);
users.forEach(System.out::println);
}
**注意:**map中的key對(duì)應(yīng)的是數(shù)據(jù)庫中的列名。例如數(shù)據(jù)庫user_id,實(shí)體類是userId,這時(shí)map的key需要填寫user_id
4、分頁
MyBatis Plus自帶分頁插件,只要簡(jiǎn)單的配置即可實(shí)現(xiàn)分頁功能
(1)創(chuàng)建配置類
此時(shí)可以刪除主類中的 @MapperScan 掃描注解
@Configuration
@MapperScan("com.mapper")
public class MyConfig {
/**
* 分頁插件
*/
@Bean
public PaginationInterceptor paginationInterceptor() {
return new PaginationInterceptor();
}
}
(2)測(cè)試selectPage分頁(自己用的)
測(cè)試:最終通過page對(duì)象獲取相關(guān)數(shù)據(jù)
/**
* 分頁查詢
*/
@Test
void pages(){
//1.創(chuàng)建page對(duì)象
//傳入兩個(gè)參數(shù):當(dāng)前 頁 和 每頁顯示記錄數(shù)
Page<User> page=new Page<User>(1,5);
//調(diào)用mp分頁查詢的方法
//調(diào)用mp分頁查詢過程中,底層封裝
//把分頁所有數(shù)據(jù)封裝到page對(duì)象里面
userMapper.selectPage(page,null);
//通過page對(duì)象獲取分頁數(shù)據(jù)
System.out.println(page.getCurrent());
System.out.println(page.getRecords());
System.out.println(page.getSize());
System.out.println(page.getTotal());
System.out.println(page.getPages());
System.out.println(page.hasNext());
System.out.println(page.hasPrevious());
}
控制臺(tái)sql語句打印:SELECT id,name,age,email,create_time,update_time FROM user LIMIT 0,5
(3)測(cè)試selectMapsPage分頁:結(jié)果集是Map(zjd沒有用過)
@Test
public void testSelectMapsPage() {
Page<User> page = new Page<>(1, 5);
IPage<Map<String, Object>> mapIPage = userMapper.selectMapsPage(page, null);
//注意:此行必須使用 mapIPage 獲取記錄列表,否則會(huì)有數(shù)據(jù)類型轉(zhuǎn)換錯(cuò)誤
mapIPage.getRecords().forEach(System.out::println);
System.out.println(page.getCurrent());
System.out.println(page.getPages());
System.out.println(page.getSize());
System.out.println(page.getTotal());
System.out.println(page.hasNext());
System.out.println(page.hasPrevious());
}
6.delete
1、根據(jù)id刪除記錄
@Test
public void testDeleteById(){
int result = userMapper.deleteById(8L);
System.out.println(result);
}
2、批量刪除
@Test
public void testDeleteBatchIds() {
int result = userMapper.deleteBatchIds(Arrays.asList(8, 9, 10));
System.out.println(result);
}
3、簡(jiǎn)單的條件查詢刪除
@Test
public void testDeleteByMap() {
HashMap<String, Object> map = new HashMap<>();
map.put("name", "Helen");
map.put("age", 18);
int result = userMapper.deleteByMap(map);
System.out.println(result);
}
4、*邏輯刪除
物理刪除:真實(shí)刪除,將對(duì)應(yīng)數(shù)據(jù)從數(shù)據(jù)庫中刪除,之后查詢不到此條被刪除數(shù)據(jù)
邏輯刪除:假刪除,將對(duì)應(yīng)數(shù)據(jù)中代表是否被刪除字段狀態(tài)修改為“被刪除狀態(tài)”,之后在數(shù)據(jù)庫中仍舊能看到此條數(shù)據(jù)記錄
(1)數(shù)據(jù)庫中添加 deleted字段
ALTER TABLE `user` ADD COLUMN `deleted` boolean

(2)實(shí)體類添加deleted 字段
并加上 @TableLogic 注解 和 @TableField(fill = FieldFill.INSERT) 注解
@TableLogic @TableField(fill = FieldFill.INSERT) private Integer deleted;
(3)元對(duì)象處理器接口添加deleted的insert默認(rèn)值
@Controller
public class MyMetaObjectHandler implements MetaObjectHandler {
/**
* 插入時(shí)時(shí)間
* @param metaObject
*/
@Override
public void insertFill(MetaObject metaObject) {
this.setFieldValByName("createTime",new Date(),metaObject);
this.setFieldValByName("updateTime",new Date(),metaObject);
this.setFieldValByName("version",1,metaObject);
//看這里********
this.setFieldValByName("deleted",0,metaObject);
}
/**
* 修改時(shí)時(shí)間
* @param metaObject
*/
@Override
public void updateFill(MetaObject metaObject) {
this.setFieldValByName("updateTime",new Date(),metaObject);
}
}
(4)application.properties 加入配置
此為默認(rèn)值,如果你的默認(rèn)值和mp默認(rèn)的一樣,該配置可無
mybatis-plus.global-config.db-config.logic-delete-value=1 mybatis-plus.global-config.db-config.logic-not-delete-value=0
(5)在 MyConfig 中注冊(cè) Bean
@Bean
public ISqlInjector sqlInjector() {
return new LogicSqlInjector();
}
(6)測(cè)試邏輯刪除
測(cè)試后發(fā)現(xiàn),數(shù)據(jù)并沒有被刪除,deleted字段的值由0變成了1
測(cè)試后分析打印的sql語句,是一條update
**注意:**被刪除數(shù)據(jù)的deleted 字段的值必須是 0,才能被選取出來執(zhí)行邏輯刪除的操作
/**
* 測(cè)試 邏輯刪除
*/
@Test
public void testLogicDelete() {
int result = userMapper.deleteById(1L);
System.out.println(result);
}
(7)測(cè)試邏輯刪除后的查詢
MyBatis Plus中查詢操作也會(huì)自動(dòng)添加邏輯刪除字段的判斷
/**
* 測(cè)試 邏輯刪除后的查詢:
* 不包括被邏輯刪除的記錄
*/
@Test
public void testLogicDeleteSelect() {
User user = new User();
List<User> users = userMapper.selectList(null);
users.forEach(System.out::println);
}
測(cè)試后分析打印的sql語句,包含 WHERE deleted=0
SELECT id,name,age,email,create_time,update_time,deleted FROM user WHERE deleted=0
7.性能分析
性能分析攔截器,用于輸出每條 SQL 語句及其執(zhí)行時(shí)間
SQL 性能執(zhí)行分析,開發(fā)環(huán)境使用,超過指定時(shí)間,停止運(yùn)行。有助于發(fā)現(xiàn)問題
1、配置插件
(1)參數(shù)說明
參數(shù):maxTime: SQL 執(zhí)行最大時(shí)長(zhǎng),超過自動(dòng)停止運(yùn)行,有助于發(fā)現(xiàn)問題。
參數(shù):format: SQL是否格式化,默認(rèn)false。
(2)在 MyConfig 中配置
/**
* SQL 執(zhí)行性能分析插件
* 開發(fā)環(huán)境使用,線上不推薦。 maxTime 指的是 sql 最大執(zhí)行時(shí)長(zhǎng)
*
* 三種環(huán)境
*dev: 開發(fā)環(huán)境
* test: 測(cè)試環(huán)境
* prod: 生產(chǎn)環(huán)境
*
*
*/
@Bean
@Profile({"dev","test"})// 設(shè)置 dev test 環(huán)境開啟
public PerformanceInterceptor performanceInterceptor() {
PerformanceInterceptor performanceInterceptor = new PerformanceInterceptor();
performanceInterceptor.setMaxTime(500);//ms/毫秒,超過此處設(shè)置的ms則sql不執(zhí)行
performanceInterceptor.setFormat(true);
return performanceInterceptor;
}
(3)Spring Boot 中設(shè)置dev環(huán)境
#環(huán)境設(shè)置:dev、test、prod spring.profiles.active=dev
2、測(cè)試
(1)常規(guī)測(cè)試
/**
* 測(cè)試 性能分析插件
*/
@Test
public void testPerformance() {
User user = new User();
user.setName("我是Helen");
user.setEmail("helen@sina.com");
user.setAge(18);
userMapper.insert(user);
}
輸出:

(2)將maxTime 改小之后再次進(jìn)行測(cè)試
performanceInterceptor.setMaxTime(5);//ms,超過此處設(shè)置的ms不執(zhí)行
如果執(zhí)行時(shí)間過長(zhǎng),則拋出異常:The SQL execution time is too large,
輸出:

8.其它
如果想進(jìn)行復(fù)雜條件查詢,那么需要使用條件構(gòu)造器 Wapper,涉及到如下方法
1、delete
2、selectOne
3、selectCount
4、selectList
5、selectMaps
6、selectObjs
7、update
十一.條件構(gòu)造器_wapper介紹
1.wapper介紹

Wrapper : 條件構(gòu)造抽象類,最頂端父類
AbstractWrapper : 用于查詢條件封裝,生成 sql 的 where 條件
QueryWrapper : Entity 對(duì)象封裝操作類,不是用lambda語法
UpdateWrapper : Update 條件封裝,用于Entity對(duì)象更新操作
AbstractLambdaWrapper : Lambda 語法使用 Wrapper統(tǒng)一處理解析 lambda 獲取 column。
LambdaQueryWrapper :看名稱也能明白就是用于Lambda語法使用的查詢Wrapper
LambdaUpdateWrapper : Lambda 更新封裝Wrapper
2.AbstractWrapper
注意:以下條件構(gòu)造器的方法入?yún)⒅械?column 均表示數(shù)據(jù)庫字段
1、ge、gt、le、lt、isNull、isNotNull
@Test
public void testDelete() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper
.isNull("name")
.ge("age", 12)
.isNotNull("email");
int result = userMapper.delete(queryWrapper);
System.out.println("delete return count = " + result);
}
SQL:UPDATE user SET deleted=1 WHERE deleted=0 AND name IS NULL AND age >= ? AND email IS NOT NULL
2、eq、ne
注意:seletOne 返回的是一條實(shí)體記錄,當(dāng)出現(xiàn)多條時(shí)會(huì)報(bào)錯(cuò)
@Test
public void testSelectOne() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "Tom");
User user = userMapper.selectOne(queryWrapper);
System.out.println(user);
}
SELECT id,name,age,email,create_time,update_time,deleted,version FROM user WHERE deleted=0 AND name = ?
3、between、notBetween
包含大小邊界
@Test
public void testSelectCount() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.between("age", 20, 30);
Integer count = userMapper.selectCount(queryWrapper);
System.out.println(count);
}
SELECT COUNT(1) FROM user WHERE deleted=0 AND age BETWEEN ? AND ?
4、allEq
@Test
public void testSelectList() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
Map<String, Object> map = new HashMap<>();
map.put("id", 2);
map.put("name", "Jack");
map.put("age", 20);
queryWrapper.allEq(map);
List<User> users = userMapper.selectList(queryWrapper);
users.forEach(System.out::println);
}
SELECT id,name,age,email,create_time,update_time,deleted,version
FROM user WHERE deleted=0 AND name = ? AND id = ? AND age = ?
5、like、notLike、likeLeft、likeRight
selectMaps返回Map集合列表
@Test
public void testSelectMaps() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper
.notLike("name", "e")
.likeRight("email", "t");
List<Map<String, Object>> maps = userMapper.selectMaps(queryWrapper);//返回值是Map列表
maps.forEach(System.out::println);
}
SELECT id,name,age,email,create_time,update_time,deleted,version
FROM user WHERE deleted=0 AND name NOT LIKE ? AND email LIKE ?
6、in、notIn、inSql、notinSql、exists、notExists
in、notIn:
①notIn(“age”,{1,2,3})—>age not in (1,2,3)
②notIn(“age”, 1, 2, 3)—>age not in (1,2,3)
inSql、notinSql:可以實(shí)現(xiàn)子查詢
①例: inSql(“age”, “1,2,3,4,5,6”)—>age in (1,2,3,4,5,6)
②例: inSql(“id”, “select id from table where id < 3”)—>id in (select id from table where id < 3)
@Test
public void testSelectObjs() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
//queryWrapper.in("id", 1, 2, 3);
queryWrapper.inSql("id", "select id from user where id < 3");
List<Object> objects = userMapper.selectObjs(queryWrapper);//返回值是Object列表
objects.forEach(System.out::println);
}
SELECT id,name,age,email,create_time,update_time,deleted,version
FROM user WHERE deleted=0 AND id IN (select id from user where id < 3)
7、or、and
注意:這里使用的是 UpdateWrapper
不調(diào)用or則默認(rèn)為使用 and 連
@Test
public void testUpdate1() {
//修改值
User user = new User();
user.setAge(99);
user.setName("Andy");
//修改條件
UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
userUpdateWrapper
.like("name", "h")
.or()
.between("age", 20, 30);
int result = userMapper.update(user, userUpdateWrapper);
System.out.println(result);
}
UPDATE user SET name=?, age=?, update_time=? WHERE deleted=0 AND name LIKE ? OR age BETWEEN ? AND ?
8、嵌套o(hù)r、嵌套and
這里使用了lambda表達(dá)式,or中的表達(dá)式最后翻譯成sql時(shí)會(huì)被加上圓括號(hào)
@Test
public void testUpdate2() {
//修改值
User user = new User();
user.setAge(99);
user.setName("Andy");
//修改條件
UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
userUpdateWrapper
.like("name", "h")
.or(i -> i.eq("name", "李白").ne("age", 20));
int result = userMapper.update(user, userUpdateWrapper);
System.out.println(result);
}
UPDATE user SET name=?, age=?, update_time=?
WHERE deleted=0 AND name LIKE ?
OR ( name = ? AND age <> ? )
9、orderBy、orderByDesc、orderByAsc
@Test
public void testSelectListOrderBy() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.orderByDesc("id");
List<User> users = userMapper.selectList(queryWrapper);
users.forEach(System.out::println);
}
SELECT id,name,age,email,create_time,update_time,deleted,version
FROM user WHERE deleted=0 ORDER BY id DESC
10、last
直接拼接到 sql 的最后
注意:只能調(diào)用一次,多次調(diào)用以最后一次為準(zhǔn) 有sql注入的風(fēng)險(xiǎn),請(qǐng)謹(jǐn)慎使用
@Test
public void testSelectListLast() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.last("limit 1");
List<User> users = userMapper.selectList(queryWrapper);
users.forEach(System.out::println);
}
}
SELECT id,name,age,email,create_time,update_time,deleted,version
FROM user WHERE deleted=0 limit 1
11、指定要查詢的列
@Test
public void testSelectListColumn() {
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.select("id", "name", "age");
List<User> users = userMapper.selectList(queryWrapper);
users.forEach(System.out::println);
}
SELECT id,name,age FROM user WHERE deleted=0
12、set、setSql
最終的sql會(huì)合并 user.setAge(),以及 userUpdateWrapper.set() 和 setSql() 中 的字段
@Test
public void testUpdateSet() {
//修改值
User user = new User();
user.setAge(99);
//修改條件
UpdateWrapper<User> userUpdateWrapper = new UpdateWrapper<>();
userUpdateWrapper
.like("name", "h")
.set("name", "老李頭")//除了可以查詢還可以使用set設(shè)置修改的字段
.setSql(" email = '123@qq.com'");//可以有子查詢
int result = userMapper.update(user, userUpdateWrapper);
}
UPDATE user SET age=?, update_time=?, name=?, email = ‘123@qq.com' WHERE deleted=0 AND name LIKE ?
(自己打的)
//mp實(shí)現(xiàn)復(fù)雜查詢操作
@Test
public void testSelectQuery() {
//創(chuàng)建QueryWrapper對(duì)象
QueryWrapper<User> wrapper = new QueryWrapper<>();
//通過QueryWrapper設(shè)置條件
//ge、gt、le、lt
//查詢age>=30記錄
//第一個(gè)參數(shù)字段名稱,第二個(gè)參數(shù)設(shè)置值
wrapper.ge("age",30);
//eq:等于、ne:不等于
//wrapper.eq("name","lilei");
//wrapper.ne("name","lilei");
//between:兩者之間
//查詢年齡 20-30
// wrapper.between("age",20,30);
//like
//wrapper.like("name","岳");
//orderByDesc
// wrapper.orderByDesc("id");
//last
//wrapper.last("limit 1");
//指定要查詢的列
// wrapper.select("id","name");
List<User> users = userMapper.selectList(wrapper);
for (User user : users) {
System.out.println(user);
}
}
總結(jié)
到此這篇關(guān)于Mybatis_plus基礎(chǔ)教程(總結(jié)篇)的文章就介紹到這了,更多相關(guān)Mybatis plus基礎(chǔ)內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
- 完美解決MybatisPlus插件分頁查詢不起作用總是查詢?nèi)繑?shù)據(jù)問題
- springboot集成mybatis-plus遇到的問題及解決方法
- Mybatis-Plus3.2.0 MetaObjectHandler 無法進(jìn)行公共字段全局填充
- springboot集成mybatisplus實(shí)例詳解
- mybatis plus使用redis作為二級(jí)緩存的方法
- MyBatisPlus 自定義sql語句的實(shí)現(xiàn)
- Mybatis-Plus 多表聯(lián)查分頁的實(shí)現(xiàn)代碼
- Mybatis-Plus 搭建與使用入門(小結(jié))
- SpringBoot Mybatis Plus公共字段自動(dòng)填充功能
相關(guān)文章
java中如何使用BufferedImage判斷圖像通道順序并轉(zhuǎn)RGB/BGR
這篇文章主要介紹了java中如何BufferedImage判斷圖像通道順序并轉(zhuǎn)RGB/BGR的相關(guān)資料,需要的朋友可以參考下2017-03-03
java中Callback簡(jiǎn)單使用總結(jié)
正好學(xué)習(xí)到j(luò)ava Callback,就整理了一下,希望整理的文章內(nèi)容對(duì)大家有所幫助2017-04-04
application.yaml與bootstrap.yaml的使用
這篇文章主要介紹了application.yaml與bootstrap.yaml的使用方式,具有很好的參考價(jià)值,希望對(duì)大家有所幫助,如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2024-08-08
Java+opencv3.2.0實(shí)現(xiàn)模板匹配
這篇文章主要為大家詳細(xì)介紹了Java+opencv3.2.0實(shí)現(xiàn)模板匹配的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-02-02

