chuyx筆記-MybatisPlus
Mybatis-plus
介紹
MyBatis-Plus(簡稱 MP)是一個 MyBatis 的增強工具,在 MyBatis 的基礎上只做增強不做改變,為簡化開發、提高效率而生。
特性
-
無侵入:只做增強不做改變,引入它不會對現有工程產生影響,如絲般順滑
-
損耗小:啟動即會自動注入基本 CURD,效能基本無損耗,直接物件導向操作
-
強大的 CRUD 操作:內建通用 Mapper、通用 Service,僅僅通過少量配置即可實現單表大部分 CRUD 操作,更有強大的條件構造器,滿足各類使用需求
-
支援 Lambda 形式呼叫:通過 Lambda 表示式,方便的編寫各類查詢條件,無需再擔心欄位寫錯
-
支援主鍵自動生成:支援多達 4 種主鍵策略(內含分散式唯一 ID 生成器 - Sequence),可自由配置,完美解決主鍵問題
-
支援 ActiveRecord 模式:支援 ActiveRecord 形式呼叫,實體類只需繼承 Model 類即可進行強大的 CRUD 操作
-
支援自定義全域性通用操作:支援全域性通用方法注入( Write once, use anywhere )
-
內建程式碼生成器:採用程式碼或者 Maven 外掛可快速生成 Mapper 、 Model 、 Service 、 Controller 層程式碼,支援模板引擎,更有超多自定義配置等您來使用
-
內建分頁外掛:基於 MyBatis 物理分頁,開發者無需關心具體操作,配置好外掛之後,寫分頁等同於普通 List 查詢
-
分頁外掛支援多種資料庫:支援 MySQL、MariaDB、Oracle、DB2、H2、HSQL、SQLite、Postgre、SQLServer 等多種資料庫
-
內建效能分析外掛:可輸出 Sql 語句以及其執行時間,建議開發測試時啟用該功能,能快速揪出慢查詢
-
內建全域性攔截外掛:提供全表 delete 、 update 操作智慧分析阻斷,也可自定義攔截規則,預防誤操作
框架結構
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-sS0NdPZJ-1605533209752)(C:\Users\cyx\AppData\Roaming\Typora\typora-user-images\image-20200701175722021.png)]
依賴
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.3.1.RELEASE</version>
<relativePath/>
</parent>
yml中的資料庫配置
# DataSource Config
spring:
datasource:
driver-class-name: org.h2.Driver
schema: classpath:db/schema-h2.sql
data: classpath:db/data-h2.sql
url: jdbc:h2:mem:test
username: root
password: test
或者propertices
#連線資料的配置
spring.datasource.username=root
spring.datasource.password=123456
spring.datasource.url=jdbc:mysql://localhost:3306/mybatisplus?useSSL=false&useUnicode=true&characterEncoding=utf-8&serverTimezone=GMT%2B8
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
入門案列注意事項:資料庫的欄位名必須和po類的屬性一一對應,不能有絲毫差錯。否則報低階sql語句錯誤,打臉!!!
入門所需類:po與資料庫欄位一一對應的實體類,繼承了BaseMapper的Mapper介面,並且需要加入@Repository註解配置bean。
CRUD
插入:
Mapper.insert(po類); //返回一個int型別的值,代表插入了多少行(影響了幾行)
當po類並沒有設定id時,mp會自動設定id,採用的是雪花演算法
常用註解:
註解名 | 作用 |
---|---|
@TableName(“XXX”) | 指定該類對應的表為XXX,(註解在po類上) |
@TableId | 指定該屬性為Id(這樣才會自動採用雪花演算法填充Id) 註解在屬性上 |
@TableFiled(“XXX”) | 指定該屬性為資料庫列名為XXX的對應屬性 註解在屬性上 |
排除非表欄位的三種方式:
關鍵字:transient:表明這個屬性是非表欄位,不參與與資料的對映關係,不參與序列化放在型別前
標識為靜態變數:全類一份,不參與和資料的對映
@TableField(exist = false):不參與和資料庫的對映,註解在屬性上
普通查詢
T Mapper.selectById(Serializable Id):有主鍵查記錄
/**
* <p>
* 根據 ID 刪除
* </p>
*
* @param id 主鍵ID
*/
int deleteById(Serializable id);
List Mapper.selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList)
/**
* <p>
* 查詢(根據ID 批量查詢)
* </p>
*
* @param idList 主鍵ID列表(不能為 null 以及 empty)
*/
List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
List Mapper.selectByMap(Map<Object, Object> columnMap):map的key對應資料庫的欄位,value對應資料庫對應的值
精準查詢。如:
Map<String,Object> map = new HashMap<>();
map.put("id",1);
map.put("name","張山");
List<User> users = userMapper.selectBymap(map);
這個就相當於sql:select * from user where id = 1 and name = '張三';
/**
* <p>
* 查詢(根據 columnMap 條件)
* </p>
*
* @param columnMap 表欄位 map 物件
*/
List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
條件構造器的查詢
條件構造器:QueryWrapper 繼承了 AbstracWrapper
兩種方式建立:QueryWrapper w1 = new QueryWrapper<>(); QueryWrapper w2 = Warppers..query(); 版本3.1.0之後採用
//名字中包含了雨並且年齡小於40
@Test
public void test20(){
QueryWrapper<Emp> userQueryWrapper = new QueryWrapper<>();
// QueryWrapper<User> query = Wrappers.<User>query();
userQueryWrapper.like("name", "雨").lt("age", 40);
List<Emp> emps = empMapper.selectList(userQueryWrapper);
emps.forEach(System.out::println);
}
//名字中包含了雨並且年齡大於等於20小於等於40並且email不為空
@Test
public void test21(){
QueryWrapper<Emp> userQueryWrapper = new QueryWrapper<>();
// QueryWrapper<User> query = Wrappers.<User>query();
userQueryWrapper.like("name", "雨").between("age",20,40)
.isNotNull("email");
List<Emp> emps = empMapper.selectList(userQueryWrapper);
emps.forEach(System.out::println);
}
//名字中為王姓或者年齡大於等於25,按照年齡降序排序,年齡相同按照id排序
@Test
public void test22(){
QueryWrapper<Emp> userQueryWrapper = new QueryWrapper<>();
// QueryWrapper<User> query = Wrappers.<User>query();
userQueryWrapper.likeRight("name","王").or().ge("age",25)
.orderByDesc("age").orderByAsc("id");
List<Emp> emps = empMapper.selectList(userQueryWrapper);
emps.forEach(System.out::println);
}
//建立日期為2019-2-14並且直屬上級名字為王姓
@Test
public void test23(){
QueryWrapper<Emp> query = Wrappers.<Emp>query();
query.apply("date_format(create_time,'%Y-%m-%d') = {0}","2019-01-11")
.inSql("manger_id","select id from emp where name like '王%'");
List<Emp> emps = empMapper.selectList(query);
emps.forEach(System.out::println);
}
//名字為王姓並且(年齡小於40或郵箱不為空)
@Test
public void test24(){
QueryWrapper<Emp> query = Wrappers.<Emp>query();
query.likeRight("name", "王")
.and((empp) -> {
empp.lt("age", 40)
.or()
.isNotNull("email");
return empp;
});
List<Emp> emps = empMapper.selectList(query);
emps.forEach(System.out::println);
}
//名字為王姓或者 (年齡小於40並且年齡大於20並且郵箱不為空)
@Test
public void test25(){
QueryWrapper<Emp> query = Wrappers.<Emp>query();
query.likeRight("name", "王")
.or(qw -> qw.lt("age", 40)
.and(qw2 -> qw2.gt("age", 20)
.and(qw3 -> qw3.isNotNull("email"))));
List<Emp> emps = empMapper.selectList(query);
emps.forEach(System.out::println);
}
//年齡為30,31,34,34的
@Test
public void test26(){
QueryWrapper<Emp> query = Wrappers.<Emp>query();
query.in("age", Arrays.asList(30,31,34,35));
List<Emp> emps = empMapper.selectList(query);
emps.forEach(System.out::println);
}
//(年齡小於40或者郵箱不為空) 並且為王姓
@Test
public void test27(){
QueryWrapper<Emp> query = Wrappers.<Emp>query();
query.nested(qw -> qw.lt("age", 40)
.or()
.isNotNull("email"))
.likeRight("name", "王");
List<Emp> emps = empMapper.selectList(query);
emps.forEach(System.out::println);
}
補充不常用條件構造器:
一:nested(fun) : 放在前面的宣告式函式,裡面是函式型介面
二:last(String sql):直接拼接sql語句,一般放最後,只能用一次,多次使用只會拼接最後的last,慎用,有sql注入的風險
select中欄位不全出現的欄位
一、在queryWrapper中新增select(“key”…):
如:queryWrapper.select(“id”, “name”)… //只查詢id,name兩個欄位
二、在queryWrapper中新增select(po.class, Predicate);
如:
queryWrapper.select(Emp.class, info -> !info.getColumn().equals("update_time")&& !info.getColumn().equals("manger_id")); 斷言式介面,排除update_time, manger_id兩個欄位,其他欄位能查出。
condition的作用
大多方法其實都可以多一個condition的引數,它為一個boolean值,為false時該條件不加入sql,為true時該條件加入sql,用於前端輸入沒輸入都可查詢。比如:場景為前端有個查詢頁面,有兩個輸入框,輸入框可有值可沒值,有值是設condition為true,加入條件,反之則反
建立條件構造器傳入實體物件
會將實體物件中的值獲取出來作為條件進行等值查詢
**當不想使用等值時:**在欄位上加@TableName(condition = SqlCondition.XXX),裡面有很多常量,如下
public static final String EQUAL = "%s=#{%s}"; public static final String NOT_EQUAL = "%s<>#{%s}"; public static final String LIKE = "%s LIKE CONCAT('%%',#{%s},'%%')"; public static final String LIKE_LEFT = "%s LIKE CONCAT('%%',#{%s})"; public static final String LIKE_RIGHT = "%s LIKE CONCAT(#{%s},'%%')"; 也可以仿照%s LIKE CONCAT(#{%s},'%%'這種新式自定義:第一個%s可以理解為列名,CONCAT(#{%s},'%%'理解為傳進去的
條件構造器中的allEq的使用
- allEq(Map<R, V> params) : 裡面的key對應欄位,value對應值
- allEq(BiPredicate<R, V> filter, Map<R, V> params, boolean flag) : flag用來判斷忽略不忽略null
- allEq(BiPredicate<R, V> filter, Map<R, V> params) :
BiPredicate<R, V> 是一個函式式介面,傳入兩個引數,傳出一個boolean,當boolean值為false的時候,該欄位將被過濾
以上都有加condition的過載函式
其他以條件構造器為引數的查詢方法
/**
* 根據 Wrapper 條件,查詢全部記錄
*
* @param queryWrapper 實體物件封裝操作類(可以為 null)
*/
List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根據 Wrapper 條件,查詢全部記錄
* <p>注意: 只返回第一個欄位的值</p>
*
* @param queryWrapper 實體物件封裝操作類(可以為 null)
*/
List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根據 Wrapper 條件,查詢總記錄數
*
* @param queryWrapper 實體物件封裝操作類(可以為 null)
*/
Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根據 Wrapper 條件,查詢全部記錄
* <p>注意: 只返回第一個欄位的值</p>
*
* @param queryWrapper 實體物件封裝操作類(可以為 null)
*/
List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
==注意:==當返回兩條記錄時,會報錯
lambda條件構造器:提供了仿誤寫功能
構建lambda條件構造器的三種方式
@Test
public void queryWrapperLambda(){
LambdaQueryWrapper<Emp> lambda = new QueryWrapper<Emp>().lambda();
LambdaQueryWrapper<Emp> empLambdaQueryWrapper = new LambdaQueryWrapper<>();
LambdaQueryWrapper<Emp> empLambdaQueryWrapper1 = Wrappers.<Emp>lambdaQuery();
}
使用示例:
@Test
public void queryWrapperLambda(){
LambdaQueryWrapper<Emp> empLambdaQueryWrapper1 = Wrappers.<Emp>lambdaQuery();
empLambdaQueryWrapper1.like(Emp::getName,"雨");
List<Emp> emps = empMapper.selectList(empLambdaQueryWrapper1);
emps.forEach(System.out::println);
}
還有一種構造器,3.0.7新增的:
@Test
public void queryWrapperLambda22(){
List<Emp> emps = new LambdaQueryChainWrapper<Emp>(empMapper)
.like(Emp::getName, "雨")
.list();
emps.forEach(System.out::println);
}
一個實體類泛型,一個mapper介面。最後的list是吧得到的變成list,否則是一個LambdaQueryChainWrapper
條件構造器常用方法
[外鏈圖片轉存失敗,源站可能有防盜鏈機制,建議將圖片儲存下來直接上傳(img-WBzUyj20-1605533209759)(C:\Users\cyx\AppData\Roaming\Typora\typora-user-images\image-20200701175511933.png)]
使用條件構造器的自定義sql(版本大於3.0.7)
@Repository
public interface EmpMapper extends BaseMapper<Emp> {
@Select("select * from emp ${ew.customSqlSegment}")
List<Emp> selectAll(@Param(Constants.WRAPPER) LambdaQueryWrapper<Emp> wrappers);
}
--------------------------------------------------------------------------------------------
@Test
public void queryWrapperMy(){
LambdaQueryWrapper<Emp> empLambdaQueryWrapper1 = Wrappers.<Emp>lambdaQuery();
empLambdaQueryWrapper1.like(Emp::getName,"雨");
List<Emp> emps = empMapper.selectAll(empLambdaQueryWrapper1);
emps.forEach(System.out::println);
}
細節:@Select裡的${ew.customSqlSegment}是固定寫法,@Param也是
也可以寫在xml中,但是要在主配置檔案中宣告
mybatis-plus: mapper-locations: - 路徑
xml中
匯入約束略 <mapper namespace="全路徑"> <select id="" resulttype=""> sql語句(寫法和註解裡面一樣的) </select> </mapper>
分頁查詢
物理分頁外掛,寫一個配置類
@MapperScan("com.chuyx.mp.mapper")
@EnableTransactionManagement
@Configuration
public class MyBatatisplusConfig {
//分頁外掛
@Bean
public PaginationInterceptor paginationInterceptor() {
PaginationInterceptor paginationInterceptor = new PaginationInterceptor();
return paginationInterceptor;
}
}
呼叫:
@Test
public void queryPage(){
LambdaQueryWrapper<Emp> wrapper = Wrappers.<Emp>lambdaQuery().like(Emp::getName, "雨");
Page<Emp> empPage = new Page<>(1, 2);
IPage<Emp> empIPage = empMapper.selectPage(empPage, wrapper);
List<Emp> records = empIPage.getRecords();
records.forEach(System.out::println);
System.out.println("總記錄數:"+empIPage.getTotal());
System.out.println("總頁數:"+empIPage.getPages());
}
提示:配置類的註解@Configuration
記得將外掛講給Spring容器管理
呼叫時new的Page需要泛型,如上第一個引數是當且頁,第二個引數是條件構造器
查出來是一個IPage,有很多方法,如過去總記錄數,總頁數,過去所有記錄等
原始碼:
/**
* 根據 entity 條件,查詢全部記錄(並翻頁)
*
* @param page 分頁查詢條件(可以為 RowBounds.DEFAULT)
* @param queryWrapper 實體物件封裝操作類(可以為 null)
*/
IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
/**
* 根據 Wrapper 條件,查詢全部記錄(並翻頁)
*
* @param page 分頁查詢條件
* @param queryWrapper 實體物件封裝操作類
*/
IPage<Map<String, Object>> selectMapsPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
selectMapsPage返回值:
key為欄位,Object為值
核心功能補充
基礎回憶
orderByDesc(“欄位”):降序排序
orderByASC(“欄位”):升序排序
ps:本文集各類文章(百度百科、SCDN部落格,其他人筆記)加自己理解整合,如有侵權請告知,會立即刪除!
相關文章
- SpringBoot學習筆記13——MybatisPlus條件查詢Spring Boot筆記MyBatis
- MyBatisPlusMyBatis
- MybatisPlus_01MyBatis
- MyBatisPlus詳解MyBatis
- 增強MybatisPlus擴充新功能 實戰MybatisPlus大合集MyBatis
- mybatisplus程式碼生成MyBatis
- t04_mybatisplusMyBatis
- MyBatisPlus入門學習MyBatis
- MybatisPlus中的update操作MyBatis
- MyBatisPlus-常用註解MyBatis
- MybatisPlus二級快取MyBatis快取
- MyBatisPlusの效率與提升MyBatis
- 印象筆記 --- 方法分享筆記筆記
- MybatisPlus - [05] 邏輯刪除MyBatis
- 筆記筆記
- mybatisPlus分頁外掛的使用MyBatis
- 穀粒學院-2-mybatisplusMyBatis
- mybatisplus欄位值自動填充MyBatis
- MybatisPlus的一些補充MyBatis
- CUUG筆記 ORACLE索引學習筆記筆記Oracle索引
- 主動筆記與被動筆記筆記
- 淘寶記錄筆記筆記
- 一步一步上手MyBatisPlusMyBatis
- MybatisPlus 中的API 使用總結(CRUD)MyBatisAPI
- 實現MyBatisPlus自定義sql注入器MyBatisSQL
- MybatisPlus - [03] 樂觀鎖&悲觀鎖MyBatis
- MyBatisPlus怎麼多表關聯查詢?MyBatis
- 心情筆記筆記
- 命令筆記筆記
- 筆記:Docker筆記Docker
- Meteor筆記筆記
- ES筆記筆記
- AbstractQueuedSynchronizer筆記筆記
- new筆記筆記
- vio筆記筆記
- Liunx筆記筆記
- Nacos 筆記筆記
- oracle筆記Oracle筆記