一起来学Mybatis Plus(四) & Service CRUD接口

前言

目前正在出一个Mybatis Plus系列教程, 篇幅会较多, 喜欢的话,给个关注❤️ ~

之前给大家讲过Mybatis教程,而MyBatis-Plus 是一个 MyBatis 的增强工具,在MyBatis的基础上只做增强不做改变,为简化开发、提高效率而生。大家需要注意的是它只是一个工具,大家需要掌握和重点学习的依然是Mybatis,在熟练掌握基础的情况下使用MyBatis-Plus会达到事半功倍的效果。

好了, 废话不多说直接开整吧~

在第一节中给大家快速体验了一下基本的crud,本节带大家详细的介绍下内置的一些crud接口

Service & CRUD

细心的小伙伴可能发现在生成的UserService接口中继承了IService接口,该接口是由MyBatisPlus提供的,内置了诸多的crud方法,接下来一起看下如何使用

Save

java 复制代码
// 插入一条记录(选择字段,策略插入)
boolean save(T entity);
// 插入(批量)
boolean saveBatch(Collection<T> entityList);
// 插入(批量)
boolean saveBatch(Collection<T> entityList, int batchSize);

下面一起测试一下:

java 复制代码
package com.springboot.all.mybatisplus.controller;

import com.springboot.all.mybatisplus.entity.User;
import com.springboot.all.mybatisplus.service.UserService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;

import java.util.ArrayList;
import java.util.List;


@RestController
@RequestMapping("/user")
public class UserController {

    @Autowired
    private UserService userService;

    @GetMapping("/save")
    @ResponseBody
    public void saveUser() {
        User user = new User();
        user.setName("小明");
        user.setAge(18);
        user.setVersion(1);
        userService.save(user);

        User user1 = new User();
        user1.setName("小明1");
        user1.setAge(20);
        user1.setVersion(1);

        User user2 = new User();
        user2.setName("小明2");
        user2.setAge(21);
        user2.setVersion(1);
        List<User> userList = new ArrayList<>();
        userList.add(user1);
        userList.add(user2);
        userService.saveBatch(userList);
    }
}
  • Service类,内部无需实现直接使用IService提供的接口方法
java 复制代码
public interface UserService extends IService<User> {

}

运行测试下:

log 复制代码
JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@58de5809] will not be managed by Spring
==>  Preparing: INSERT INTO sys_user ( name, age, version ) VALUES ( ?, ?, ? )
==> Parameters: 小明(String), 18(Integer), 1(Integer)
<==    Updates: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6911108f]
JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@58de5809] will be managed by Spring
==>  Preparing: INSERT INTO sys_user ( name, age, version ) VALUES ( ?, ?, ? )
==> Parameters: 小明1(String), 20(Integer), 1(Integer)
==> Parameters: 小明2(String), 21(Integer), 1(Integer)

通过日志可以看到执行成功

Update

java 复制代码
// 根据 UpdateWrapper 条件,更新记录 需要设置sqlset
boolean update(Wrapper<T> updateWrapper);
// 根据 whereWrapper 条件,更新记录
boolean update(T updateEntity, Wrapper<T> whereWrapper);
// 根据 ID 选择修改
boolean updateById(T entity);
// 根据ID 批量更新
boolean updateBatchById(Collection<T> entityList);
// 根据ID 批量更新
boolean updateBatchById(Collection<T> entityList, int batchSize);
  • Wrapper<T> updateWrapper 实体对象封装操作类 UpdateWrapper
  • T entity 实体对象
  • Collection<T> entityList 实体对象集合
  • int batchSize 更新批次数量

一起测试下:

java 复制代码
@GetMapping("/update")
@ResponseBody
public void updateUser() {
    User user = new User();
    user.setId(1731552348470849545L);
    user.setName("小明-UPDATE");
    userService.updateById(user);

    UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
    // 类似 where name = "小明1"
    updateWrapper.eq("name","小明1");
    User user1 = new User();
    user1.setName("小明1-UPDATE");
    userService.update(user1, updateWrapper);

}

结果:

log 复制代码
JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@3c78383f] will not be managed by Spring
==>  Preparing: UPDATE sys_user SET name=? WHERE id=?
==> Parameters: 小明-UPDATE(String), 1731552348470849545(Long)
<==    Updates: 1
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@268f536b]
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@2e5fec60] was not registered for synchronization because synchronization is not active
JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@3c78383f] will not be managed by Spring
==>  Preparing: UPDATE sys_user SET name=? WHERE (name = ?)
==> Parameters: 小明1-UPDATE(String), 小明1(String)
<==    Updates: 1

通用的大家在学习的过程中可以对照sql执行的情况来理解

SaveOrUpdate

java 复制代码
// TableId 注解存在更新记录,否插入一条记录
boolean saveOrUpdate(T entity);
// 根据updateWrapper尝试更新,否继续执行saveOrUpdate(T)方法
boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper);
// 批量修改插入
boolean saveOrUpdateBatch(Collection<T> entityList);
// 批量修改插入
boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);

从字面意思也很好理解,有时候我们经常会有这种需求,比如我们需要在数据库中保存一条数据,如果存在就更新,如果不存在就插入一条数据。

  • T entity 实体对象
  • Wrapper updateWrapper实体对象封装操作类UpdateWrapper`
  • Collection<T> entityList 实体对象集合
  • int batchSize 插入批次数量

下面一起来测试下:

java 复制代码
@GetMapping("/saveOrUpdate")
@ResponseBody
public void saveOrUpdateUser() {
    User user = new User();
    user.setName("小明-saveOrUpdate");
    userService.saveOrUpdate(user);

    User user1 = new User();
    user1.setId(1731552348470849551L);
    user1.setName("小明2");
    userService.saveOrUpdate(user1);



}

结果:

log 复制代码
JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@7f11356f] will be managed by Spring
==>  Preparing: SELECT id,name,age,version,create_at,update_at FROM sys_user WHERE id=?
==> Parameters: 1731552348470849551(Long)
<==    Columns: id, name, age, version, create_at, update_at
<==        Row: 1731552348470849551, 小明1, 0, null, 2023-12-19 10:14:34, 2023-12-19 10:14:34
<==      Total: 1
Releasing transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@27ff4b17]
Fetched SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@27ff4b17] from current transaction
==>  Preparing: UPDATE sys_user SET name=? WHERE id=?
==> Parameters: 小明2(String), 1731552348470849551(Long)
<==    Updates: 1

从结果来看第一条不存在所以进行了新增,第二条根据了存在所以进行了更新,我们可以看出在不指定条件的情况下根据ID主键来判断是否存在,如果存在就更新,不存在就插入一条数据。

有时候我们需要根据多个条件来判断是否存在,比如我们需要根据nameage来判断是否存在,那么我们就需要使用Wrapper来进行条件的封装操作。

java 复制代码
@GetMapping("/saveOrUpdate")
@ResponseBody
public void saveOrUpdateUser() {
    UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
    updateWrapper.eq("name","小明-saveOrUpdate");
    User user1 = new User();
    user1.setName("小明-saveOrUpdate1");
    userService.saveOrUpdate(user1, updateWrapper);
}

结果:

log 复制代码
JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@386e3ce0] will not be managed by Spring
==>  Preparing: UPDATE sys_user SET name=? WHERE (name = ?)
==> Parameters: 小明-saveOrUpdate1(String), 小明-saveOrUpdate(String)
<==    Updates: 3
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@5977861]

结果发现,因为小明-saveOrUpdate这条数据存在,所以进行了更新

Remove

java 复制代码
// 根据 queryWrapper 设置的条件,删除记录
boolean remove(Wrapper<T> queryWrapper);
// 根据 ID 删除
boolean removeById(Serializable id);
// 根据 columnMap 条件,删除记录
boolean removeByMap(Map<String, Object> columnMap);
// 删除(根据ID 批量删除)
boolean removeByIds(Collection<? extends Serializable> idList);
  • Wrapper<T> queryWrapper 实体包装类 QueryWrapper
  • Serializable id 主键 ID
  • Map<String, Object> columnMap 表字段 map 对象
  • Collection<? extends Serializable> idList 主键 ID 列表
java 复制代码
@GetMapping("/remove")
@ResponseBody
public void remove() {
    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.eq("name","小明-saveOrUpdate1");
    userService.remove(queryWrapper);


    Map<String, Object> map = new HashMap<>();
    map.put("name", "小明2");
    userService.removeByMap(map);
}

结果:

log 复制代码
JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@56a1ca2e] will not be managed by Spring
==>  Preparing: DELETE FROM sys_user WHERE (name = ?)
==> Parameters: 小明-saveOrUpdate1(String)
<==    Updates: 3
Closing non transactional SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@6661b17]
Creating a new SqlSession
SqlSession [org.apache.ibatis.session.defaults.DefaultSqlSession@71dec861] was not registered for synchronization because synchronization is not active
JDBC Connection [com.alibaba.druid.proxy.jdbc.ConnectionProxyImpl@56a1ca2e] will not be managed by Spring
==>  Preparing: DELETE FROM sys_user WHERE (name = ?)
==> Parameters: 小明2(String)
<==    Updates: 2

Get & 查询单个记录

java 复制代码
// 根据 ID 查询
T getById(Serializable id);
// 根据 Wrapper,查询一条记录。结果集,如果是多个会抛出异常,随机取一条加上限制条件 wrapper.last("LIMIT 1")
T getOne(Wrapper<T> queryWrapper);
// 根据 Wrapper,查询一条记录
T getOne(Wrapper<T> queryWrapper, boolean throwEx);
// 根据 Wrapper,查询一条记录
Map<String, Object> getMap(Wrapper<T> queryWrapper);
// 根据 Wrapper,查询一条记录
<V> V getObj(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);
  • Serializable id 主键 ID
  • Wrapper<T> queryWrapper 实体对象封装操作类 QueryWrapper
  • boolean throwEx 有多个 result 是否抛出异常
  • T entity 实体对象
  • Function<? super Object, V> mapper 转换函数

List & 查询多条记录

java 复制代码
// 查询所有
List<T> list();
// 查询列表
List<T> list(Wrapper<T> queryWrapper);
// 查询(根据ID 批量查询)
Collection<T> listByIds(Collection<? extends Serializable> idList);
// 查询(根据 columnMap 条件)
Collection<T> listByMap(Map<String, Object> columnMap);
// 查询所有列表
List<Map<String, Object>> listMaps();
// 查询列表
List<Map<String, Object>> listMaps(Wrapper<T> queryWrapper);
// 查询全部记录
List<Object> listObjs();
// 查询全部记录
<V> List<V> listObjs(Function<? super Object, V> mapper);
// 根据 Wrapper 条件,查询全部记录
List<Object> listObjs(Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录
<V> List<V> listObjs(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);
  • Wrapper<T> queryWrapper 实体对象封装操作类 QueryWrapper
  • Collection<? extends Serializable> idList 主键 ID 列表
  • Map<String, Object> columnMap 表字段 map 对象
  • Function<? super Object, V> mapper 转换函数

Page & 分页查询

java 复制代码
// 无条件分页查询
IPage<T> page(IPage<T> page);
// 条件分页查询
IPage<T> page(IPage<T> page, Wrapper<T> queryWrapper);
// 无条件分页查询
IPage<Map<String, Object>> pageMaps(IPage<T> page);
// 条件分页查询
IPage<Map<String, Object>> pageMaps(IPage<T> page, Wrapper<T> queryWrapper);
  • IPage<T> page 翻页对象
  • Wrapper<T> queryWrapper 实体对象封装操作类 QueryWrapper

Count & 查询总记录数

java 复制代码
// 查询总记录数
int count();
// 根据 Wrapper 条件,查询总记录数
int count(Wrapper<T> queryWrapper);
  • Wrapper<T> queryWrapper 实体对象封装操作类 QueryWrapper

这里不一一给大家演示了,道理都是相通的,主要给大家说下分页数据怎么查,下面是一个根据条件查询分页的例子:

java 复制代码
@GetMapping("/page")
@ResponseBody
public Object page() {
    // 创建Page对象,指定当前页和每页显示的数据条数
    Page<User> page = new Page<>(1, 10);

    QueryWrapper<User> queryWrapper = new QueryWrapper<>();
    queryWrapper.like("name","%小明%");
    page = userService.page(page, queryWrapper);

    // 获取总记录数
    long size = page.getSize();
    long total = page.getTotal();
    long current = page.getCurrent();
    // 获取分页数据列表
    List<User> list = page.getRecords();

    JSONObject json = new JSONObject();
    json.put("size", size);
    json.put("total", total);
    json.put("current", current);
    json.put("list", list);
    return json;
}

结果:

log 复制代码
==>  Preparing: SELECT id,name,age,version,create_at,update_at FROM sys_user WHERE (name LIKE ?) LIMIT ?
==> Parameters: %%小明%%(String), 10(Long)
<==    Columns: id, name, age, version, create_at, update_at
<==        Row: 1731552348470849540, 小明, 18, null, 2023-12-19 09:37:57, 2023-12-19 09:37:57
<==        Row: 1731552348470849541, 小明, 18, 1, 2023-12-19 09:40:05, 2023-12-19 09:40:05
<==        Row: 1731552348470849542, 小明, 18, 1, 2023-12-19 09:54:55, 2023-12-19 09:54:55
<==        Row: 1731552348470849545, 小明-UPDATE, 18, 1, 2023-12-19 09:57:21, 2023-12-19 10:07:48
<==        Row: 1731552348470849546, 小明1-UPDATE, 20, 1, 2023-12-19 09:57:21, 2023-12-19 10:07:48
<==        Row: 1731552348470849549, 小明1, 0, null, 2023-12-19 10:13:55, 2023-12-19 10:13:55
<==      Total: 6
json 复制代码
{"total":6,"current":1,"size":10,"list":[{"name":"小明","updateAt":"2023-12-19T01:37:57.000+00:00","id":1731552348470849540,"age":18,"createAt":"2023-12-19T01:37:57.000+00:00"},{"name":"小明","updateAt":"2023-12-19T01:40:05.000+00:00","id":1731552348470849541,"version":1,"age":18,"createAt":"2023-12-19T01:40:05.000+00:00"},{"name":"小明","updateAt":"2023-12-19T01:54:55.000+00:00","id":1731552348470849542,"version":1,"age":18,"createAt":"2023-12-19T01:54:55.000+00:00"},{"name":"小明-UPDATE","updateAt":"2023-12-19T02:07:48.000+00:00","id":1731552348470849545,"version":1,"age":18,"createAt":"2023-12-19T01:57:21.000+00:00"},{"name":"小明1-UPDATE","updateAt":"2023-12-19T02:07:48.000+00:00","id":1731552348470849546,"version":1,"age":20,"createAt":"2023-12-19T01:57:21.000+00:00"},{"name":"小明1","updateAt":"2023-12-19T02:13:55.000+00:00","id":1731552348470849549,"age":0,"createAt":"2023-12-19T02:13:55.000+00:00"}]}

此外,还需要更改一下配置,添加mubatisplus分页插件

java 复制代码
@EnableTransactionManagement
@Configuration
@MapperScan("com.springboot.all.mybatisplus.mapper")
public class MyBatisPlusConfig {

    @Bean
    public MybatisPlusInterceptor mybatisPlusInterceptor() {
        MybatisPlusInterceptor interceptor = new MybatisPlusInterceptor();
        // 注册乐观锁插件
        interceptor.addInnerInterceptor(new OptimisticLockerInnerInterceptor());
        // 注册分页插件
        interceptor.addInnerInterceptor(new PaginationInnerInterceptor(DbType.MYSQL));
        return interceptor;
    }
}

以上就是IService接口提供的crud方法,如果感兴趣的小伙伴可以看下源码

结束语

下节给大家讲解Mapper CRUD接口

本着把自己知道的都告诉大家,如果本文对有所帮助,点赞+关注鼓励一下呗~

MybatisPlus教程相关文章

往期Nginx教程相关文章

往期Docker教程相关文章

往前Shell脚本编程相关文章

往期Linux相关文章

往期面试题相关文章

项目源码(源码已更新 欢迎star⭐️)

往期设计模式相关文章

设计模式项目源码(源码已更新 欢迎star⭐️)

Kafka 专题学习

项目源码(源码已更新 欢迎star⭐️)

ElasticSearch 专题学习

项目源码(源码已更新 欢迎star⭐️)

往期并发编程内容推荐

推荐 SpringBoot & SpringCloud (源码已更新 欢迎star⭐️)

博客(阅读体验较佳)

相关推荐
uhakadotcom28 分钟前
使用postgresql时有哪些简单有用的最佳实践
后端·面试·github
IT毕设实战小研32 分钟前
基于Spring Boot校园二手交易平台系统设计与实现 二手交易系统 交易平台小程序
java·数据库·vue.js·spring boot·后端·小程序·课程设计
bobz96540 分钟前
QT 字体
后端
泉城老铁43 分钟前
Spring Boot 中根据 Word 模板导出包含表格、图表等复杂格式的文档
java·后端
用户4099322502121 小时前
如何在FastAPI中玩转APScheduler,实现动态定时任务的魔法?
后端·github·trae
风象南1 小时前
开发者必备工具:用 SpringBoot 构建轻量级日志查看器,省时又省力
后端
RainbowSea1 小时前
伙伴匹配系统(移动端 H5 网站(APP 风格)基于Spring Boot 后端 + Vue3 - 04
java·spring boot·后端
楽码1 小时前
理解自动修复:编程语言的底层逻辑
后端·算法·编程语言
RainbowSea1 小时前
伙伴匹配系统(移动端 H5 网站(APP 风格)基于Spring Boot 后端 + Vue3 - 03
java·spring boot·后端
Young55662 小时前
RAG?你真的了解RAG吗?
人工智能·后端