MyBatis-Plus中BaseMapper接口的增刪查改操作大全
入門案例當(dāng)中的“查詢所有”調(diào)用的是BaseMapper當(dāng)中的selectList,接下來我們從增刪查改來了解BaseMapper接口當(dāng)中的方法。
/**
* 查詢所有
*/
@Test
public void testSelectList(){
userMapper.selectList(null).forEach(System.out::println);
}1.查詢
根據(jù)id查詢
T selectById(Serializable id);
這個沒什么好說的就是根據(jù)id查詢,返回T類型的對象。注意Serializable,這里使用Serializable 的原因是數(shù)據(jù)庫的主鍵類型多種多樣,比如Integer、Long、String等,而Long, Integer, String 等包裝類和基本類型的包裝類都實現(xiàn)了 Serializable 接口。這就使得以Serializable作為參數(shù)類型的selectById變得很通用。
調(diào)用代碼:
/**
* 根據(jù)id查詢
*/
@Test
public void selectById(){
userMapper.selectById(1);
}運行結(jié)果:

根據(jù)多個id查詢
List<T> selectBatchIds(@Param("coll") Collection<? extends Serializable> idList);Collection是Java集合框架的根接口,List、Set、Queue等都實現(xiàn)了這個接口
? extends Serializable是泛型通配符,表示"任何繼承了Serializable接口的類型"
所以我們傳入的參數(shù)應(yīng)該是實現(xiàn)了Serializable接口的元素的集合,例如:
List<Long> idList = Arrays.asList(1L, 2L, 3L);
Set<Integer> idSet = new HashSet<>(Arrays.asList(1, 2));
List<String> idStrings = Arrays.asList("A", "B", "C");
ArrayList<BigInteger> bigInts = new ArrayList<>();selectBatchIds 接收這樣一個集合,返回T類對象的集合
調(diào)用代碼:
/**
* 批量查詢,也可以查詢一個
*/
@Test
public void selectBatchByIds() {
List<Long> idList = Arrays.asList(1L, 2L, 3L, 4L, 5L);
List<User> users = userMapper.selectBatchIds(idList);
System.out.println("查詢到 " + users.size() + " 條記錄:");
users.forEach(System.out::println);
}運行結(jié)果:

根據(jù)字段名-值對的映射關(guān)系進行查詢
List<T> selectByMap(@Param("cm") Map<String, Object> columnMap);它接受一個字段名和對應(yīng)值的Map,返回所有匹配的記錄。
生成的SQL是 等值查詢的 AND 組合,類似于:
SELECT * FROM table_name WHERE column1 = ? AND column2 = ? AND ...;
我們要注意Map當(dāng)中的字段名字是數(shù)據(jù)庫當(dāng)中的名字而不是JavaBean當(dāng)中的名字
調(diào)用代碼:這段代碼相當(dāng)于查詢了名字是Mike并且年齡為18的所有用戶,并返回它們的集合
/**
* 通過map查詢用戶信息
*/
@Test
public void selectByMap(){
//通過map條件查詢用戶信息
//SELECT id,name,age,email FROM user WHERE name = ? AND age = ?
Map<String, Object> map = new HashMap<>();
map.put("age", 18);
map.put("name", "Mike");
List<User> list = userMapper.selectByMap(map);
list.forEach(System.out::println);
}運行結(jié)果:

期望返回一條記錄的查詢
default T selectOne(@Param("ew") Wrapper<T> queryWrapper) {
// 1. 先調(diào)用 selectList 查詢所有匹配的記錄
List<T> ts = this.selectList(queryWrapper);
// 2. 檢查結(jié)果列表是否不為空
if (CollectionUtils.isNotEmpty(ts)) {
// 3. 如果結(jié)果數(shù)量不等于1,拋出異常
if (ts.size() != 1) {
throw ExceptionUtils.mpe("One record is expected, but the query result is multiple records", new Object[0]);
} else {
// 4. 如果正好只有1條記錄,返回它
return ts.get(0);
}
} else {
// 5. 如果沒有記錄,返回null
return null;
}
}QueryWrapper 是 MyBatis-Plus 提供的查詢條件封裝器,用于以面向?qū)ο蟮姆绞絼討B(tài)構(gòu)建 SQL 查詢條件,避免了手動拼接 SQL 字符串的麻煩。有了QueryWrapper 之后,我們便可以使用Java代碼來構(gòu)建SQL查詢條件,例如:
// 查詢 name = '張三' 并且 age = 25 的用戶
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name", "張三")
.eq("age", 25);
List<User> users = userMapper.selectList(queryWrapper);
// 生成SQL: SELECT * FROM user WHERE name = '張三' AND age = 25QueryWrapper還有很多復(fù)雜的用法,我們會在后面遇到。
我們可以看到selectOne調(diào)用了前面的selectList方法查詢所有符合條件的記錄,再檢查記錄條數(shù)是否是1.如果是1則返回,多余1則拋出異常,少于1則返回null
調(diào)用:這是剛好為1的情況
/**
* 查詢單條記錄
*/
@Test
public void selectOne() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("name", "Mike")
.eq("age", 18);
User user = userMapper.selectOne(wrapper);
System.out.println("查詢到的用戶: " + user);
}結(jié)果:

大于1的情況:
/**
* 查詢單條記錄
*/
@Test
public void selectOne() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("age", 89);
User user = userMapper.selectOne(wrapper);
System.out.println("查詢到的用戶: " + user);
}結(jié)果:

少于1的情況:
/**
* 查詢單條記錄
*/
@Test
public void selectOne() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.eq("age", 1111);
User user = userMapper.selectOne(wrapper);
System.out.println("查詢到的用戶: " + user);
}結(jié)果:

查詢符合條件的記錄數(shù)
Long selectCount(@Param("ew") Wrapper<T> queryWrapper);queryWrapper包裝好查詢條件,查詢到符合條件的記錄數(shù)并且返回
代碼:
/**
* 查詢記錄數(shù)量
*/
@Test
public void selectCount() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.gt("age", 20);
Long count = userMapper.selectCount(wrapper);
System.out.println("年齡大于20的用戶數(shù)量: " + count);
}結(jié)果:

查詢所有符合條件的記錄
List<T> selectList(@Param("ew") Wrapper<T> queryWrapper);在入門案例中,我們傳入了null,也就是沒有任何條件,也就是查詢所有記錄
這里我們傳入查詢條件
代碼:
/**
* 查詢所有符合條件的記錄
*/
@Test
public void testSelectList(){
QueryWrapper queryWrapper=new QueryWrapper();
queryWrapper.gt("age",50);
userMapper.selectList(queryWrapper).forEach(System.out::println);
}結(jié)果:
查詢返回Map列表
List<Map<String, Object>> selectMaps(@Param("ew") Wrapper<T> queryWrapper);這個方法主要用來返回某些特定的字段,依舊是用queryWrapper來構(gòu)造查詢條件
調(diào)用代碼:
/**
* 查詢返回Map列表
*/
@Test
public void selectMaps() {
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.select("id", "name", "age")
.lt("age", 30);//gt是大于,lt是小于
List<Map<String, Object>> maps = userMapper.selectMaps(wrapper);
System.out.println("查詢結(jié)果:");
maps.forEach(System.out::println);
}這個方法當(dāng)中查詢了年齡小于30的用戶的id,名字,年齡。
結(jié)果:

返回單個字段(一般是id)的查詢
List<Object> selectObjs(@Param("ew") Wrapper<T> queryWrapper);即使我們指定了多個字段,結(jié)果也只會返回第一列
調(diào)用:
/**
* 只返回第一列的查詢
*/
@Test
public void selectObjs(){
QueryWrapper queryWrapper=new QueryWrapper();
queryWrapper.select("id","name","email")
.eq("age","12");
System.out.println("返回的數(shù)據(jù):"+userMapper.selectObjs(queryWrapper));
}結(jié)果:

可以看到只有第一列的數(shù)據(jù)被返回,即便我們指定了name和email字段。
我們看到Columns中有三個字段,那只是數(shù)據(jù)庫SQL執(zhí)行結(jié)束的值,selectObjs只取了第一列。
分頁查詢
<P extends IPage<T>> P selectPage(P page, @Param("ew") Wrapper<T> queryWrapper);泛型:<P extends IPage<T>> - 接受任何實現(xiàn)了 IPage<T> 接口的分頁對象
IPage類:
//
// Source code recreated from a .class file by IntelliJ IDEA
// (powered by FernFlower decompiler)
//
package com.baomidou.mybatisplus.core.metadata;
import java.io.Serializable;
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
public interface IPage<T> extends Serializable {
List<OrderItem> orders();
default boolean optimizeCountSql() {
return true;
}
default boolean optimizeJoinOfCountSql() {
return true;
}
default boolean searchCount() {
return true;
}
default long offset() {
long current = this.getCurrent();
return current <= 1L ? 0L : Math.max((current - 1L) * this.getSize(), 0L);
}
default Long maxLimit() {
return null;
}
default long getPages() {
if (this.getSize() == 0L) {
return 0L;
} else {
long pages = this.getTotal() / this.getSize();
if (this.getTotal() % this.getSize() != 0L) {
++pages;
}
return pages;
}
}
default IPage<T> setPages(long pages) {
return this;
}
List<T> getRecords();
IPage<T> setRecords(List<T> records);
long getTotal();
IPage<T> setTotal(long total);
long getSize();
IPage<T> setSize(long size);
long getCurrent();
IPage<T> setCurrent(long current);
default <R> IPage<R> convert(Function<? super T, ? extends R> mapper) {
List<R> collect = (List)this.getRecords().stream().map(mapper).collect(Collectors.toList());
return this.setRecords(collect);
}
default String countId() {
return null;
}
}
參數(shù)1:P page - 分頁參數(shù)對象(頁碼、頁大小等)
參數(shù)2:@Param("ew") Wrapper<T> queryWrapper - 查詢條件
返回值:P - 包含分頁數(shù)據(jù)和分頁信息的結(jié)果對象
要調(diào)用這個接口,在實現(xiàn)它之前我們要先配置MybatisPlus的分頁插件:
package com.qcby.config;
import com.baomidou.mybatisplus.annotation.DbType;
import com.baomidou.mybatisplus.extension.plugins.MybatisPlusInterceptor;
import com.baomidou.mybatisplus.extension.plugins.inner.PaginationInnerInterceptor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
@Configuration
public class MybatisPlusConfig {
/**
* PaginationInnerInterceptor
* 分頁插件,專門處理分頁查詢
* 會自動在分頁查詢時:執(zhí)行 COUNT(*) 查詢獲取總記錄數(shù)
* 在原 SQL 上添加 LIMIT 子句(MySQL)或?qū)?yīng)的分頁語法
* 將分頁結(jié)果封裝到 Page 對象中
*
* DbType.MYSQL
* 指定數(shù)據(jù)庫類型為 MySQL
* MySQL: LIMIT offset(偏移量), size(頁大小)
* 指定類型后插件會自動生成正確的分頁 SQL
*/
@Bean
public MybatisPlusInterceptor mybatisPlusInterceptor() {
MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
// 添加分頁插件
interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
return interceptor;
}
}調(diào)用代碼:
@Test
public void selectPage() {
// 1. 創(chuàng)建分頁對象:第1頁,每頁10條
Page<User> page = new Page<>(1, 10);
// 2. 創(chuàng)建查詢條件包裝器
QueryWrapper<User> wrapper = new QueryWrapper<>();
// 3. 添加排序條件:按照age字段降序排列
wrapper.orderByDesc("age");
// 4. 執(zhí)行分頁查詢
Page<User> result = userMapper.selectPage(page, wrapper);
// 5. 輸出分頁信息
System.out.println("總記錄數(shù): " + result.getTotal());
System.out.println("當(dāng)前頁記錄:");
result.getRecords().forEach(System.out::println);
}結(jié)果:

返回特定字段的分頁查詢
<P extends IPage<Map<String, Object>>> P selectMapsPage(P page, @Param("ew") Wrapper<T> queryWrapper);代碼:
/**
* 分頁查詢返回Map,相比于普通的分頁查詢,Map可以不需要返回完整的對象,只返回部分字段
*/
@Test
public void selectMapsPage() {
Page<Map<String, Object>> page = new Page<>(1, 2);
QueryWrapper<User> wrapper = new QueryWrapper<>();
wrapper.select("id", "name");
Page<Map<String, Object>> result = userMapper.selectMapsPage(page, wrapper);
System.out.println("Map分頁結(jié)果:");
result.getRecords().forEach(System.out::println);
}結(jié)果:

我們發(fā)現(xiàn),在配置了分頁插件之后,會攔截Sql,并且生成兩條,一條查詢總記錄數(shù),一條執(zhí)行分頁查詢。
2.增(插入)
int insert(T entity);
如果要進行批量插入也只是寫循環(huán)。
調(diào)用:
/**
* 插入一條記錄
*/
@Test
public void insert(){
User user=new User();
user.setName("Steve");
user.setAge(12);
user.setEmail("test9@baomidou.com");
int res=userMapper.insert(user);
System.out.println("受影響的行數(shù):"+res);
}結(jié)果:

3.刪除
根據(jù)id刪除
int deleteById(Serializable id);
代碼:
/**
* 根據(jù)id刪除
*/
@Test
public void deleteById(){
User user=new User();
user.setId(9L);//加上L表示Long類型
int res=userMapper.deleteById(user);//也可以直接傳入id值
System.out.println("受影響的行數(shù):"+res);
}因為我的主鍵是Long類型的所以我寫了9L
結(jié)果:

傳入對象刪除
int deleteById(T entity);
這個和上面的刪除是類似的,只不過傳入的是對象。
根據(jù)Map刪除
int deleteByMap(@Param("cm") Map<String, Object> columnMap);用Map來構(gòu)造刪除條件。
調(diào)用:
/**
* 根據(jù)Map刪除
*/
@Test
public void deleteByMap(){
Map<String,Object> map=new HashMap<>();
map.put("name","Steve");//刪除名字為Steve的記錄
map.put("age",12);//刪除年齡為12的記錄
int res=userMapper.deleteByMap(map);//刪除名字為Steve且年齡為12的記錄
System.out.println("受影響的行數(shù):"+res);
}結(jié)果:

我們發(fā)現(xiàn)用Map構(gòu)造的條件只能用and連接。
根據(jù)queryWrapper刪除
我們使用這種方式刪除,可以構(gòu)造比Map更加復(fù)雜的條件。
int delete(@Param("ew") Wrapper<T> queryWrapper);代碼:
@Test
public void deleteWithQueryWrapper(){
QueryWrapper<User> wrapper=new QueryWrapper<>();
wrapper.eq("name","Steve")
.eq("age",12)
.like("email","baomidou");//刪除名字為Steve,12歲,郵箱名稱包含baomidou的記錄
// wrapper.eq("name", "Steve"); // name = 'Steve'
// wrapper.ne("name", "Steve"); // name != 'Steve'
// wrapper.gt("age", 18); // age > 18
// wrapper.ge("age", 18); // age >= 18
// wrapper.lt("age", 65); // age < 65
// wrapper.le("age", 65); // age <= 65
//模糊查詢
// wrapper.like("name", "Ste"); // name LIKE '%Ste%'
// wrapper.likeLeft("name", "eve"); // name LIKE '%eve'
// wrapper.likeRight("name", "Ste"); // name LIKE 'Ste%'
// wrapper.notLike("name", "Steve"); // name NOT LIKE '%Steve%'
//范圍查詢
// wrapper.in("age", Arrays.asList(18, 19, 20)); // age IN (18,19,20)
// wrapper.notIn("age", Arrays.asList(60, 65, 70)); // age NOT IN (60,65,70)
// wrapper.between("age", 18, 30); // age BETWEEN 18 AND 30
// wrapper.notBetween("age", 60, 100); // age NOT BETWEEN 60 AND 100
//空值判斷
// wrapper.isNull("email"); // email IS NULL
// wrapper.isNotNull("email"); // email IS NOT NULL
int res=userMapper.delete(wrapper);
System.out.println("受影響的行數(shù):"+res);
}結(jié)果:

可以看到QueryWrapper支持非常多條件。
我們?nèi)绻枰胦r連接條件的話,需要用.or()來連接,例如:
wrapper.eq("name", "Steve")
.or()
.eq("name", "Tom"); // name='Steve' OR name='Tom'批量刪除
int deleteBatchIds(@Param("coll") Collection<? extends Serializable> idList);傳入多個id刪除
代碼:
/**
* 刪除固定的幾個id,批量刪除
*/
@Test
public void deleteBatchByIds() {
List<Long> idList = Arrays.asList(1L, 2L, 3L, 4L, 5L);
int res = userMapper.deleteBatchIds(idList);
System.out.println("批量刪除了 " + res + " 條記錄");
}結(jié)果:我改成了20,21,23,24,25這個id序列,可以看到即使某些id不存在也不會報錯

4.修改
根據(jù)id修改
int updateById(@Param("et") T entity);代碼:
/**
* 根據(jù)id修改
*/
@Test
public void updateById(){
User user=new User();
user.setId(1L);
user.setAge(99);
userMapper.updateById(user);
//userMapper.update(user,null);
}結(jié)果:

queryWrapper修改
int update(@Param("et") T entity, @Param("ew") Wrapper<T> updateWrapper);這個方法可以傳入實體類和queryWrapper混合使用,也可以只傳入實體類或者只傳入queryWrapper。在根據(jù)id修改當(dāng)中,注釋的那一行就是使用的當(dāng)前方法,只不過它是只傳入的實體類。
只傳入queryWrapper:
/**
* 復(fù)雜條件wrapper修改
*/
@Test
public void updateWithWrapper(){
UpdateWrapper<User> wrapper=new UpdateWrapper<>();
wrapper.set("age",89)
.set("email","update@email.com")//set設(shè)置更新字段
.eq("name","張三")//eq設(shè)置條件
.or()//or連接
.eq("name","李四");
userMapper.update(null,wrapper);
}結(jié)果:

都傳入:
/**
* 兩種都傳入的修改
*/
@Test
public void updateWithEntityAndWrapper(){
// 創(chuàng)建實體對象-設(shè)置要更新的字段值
User user = new User();
user.setName("新名字"); // 要更新的字段
user.setEmail("new@email.com");
user.setAge(25);
// 創(chuàng)建Wrapper-設(shè)置更新條件
UpdateWrapper<User> wrapper = new UpdateWrapper<>();
wrapper.eq("age", 89); // 條件:年齡為89的用戶
System.out.println("受影響行數(shù):" + userMapper.update(user, wrapper));
}結(jié)果:

到此這篇關(guān)于MyBatis-Plus當(dāng)中BaseMapper接口的增刪查改操作的文章就介紹到這了,更多相關(guān)MyBatis-Plus增刪查改內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
springboot+vue實現(xiàn)登錄功能的最新方法整理
最近做項目時使用到了springboot+vue實現(xiàn)登錄功能的技術(shù),所以下面這篇文章主要給大家介紹了關(guān)于springboot+vue實現(xiàn)登錄功能的相關(guān)資料,文中通過實例代碼介紹的非常詳細,需要的朋友可以參考下2022-06-06

