MyBatisPlus Service层的CRUD

会当凌绝顶,一览众山小

| @Author:TTODS

MyBatisPlus框架系列文章目录:


前言

与Mapper层类似,MybatisPlus也提供了具有通用CRUD功能的Service层接口.本文将介绍如何使用MybatisPlus提供的基类与接口构建我们的Service层,以及如何使用Service层的通用CRUD.

创建UserService接口

在包com.example.service中创建一个UserService接口,并使其继承mybatis-plus提供的IService<T>接口(T表示对应实体类类型)。

package com.example.service;

import com.baomidou.mybatisplus.extension.service.IService;
import com.example.pojo.User;

public interface UserService extends IService<User> {

}

创建UserServiceImpl类

在包com.example.service.impl中创建一个UserServiceImpl类,并使其继承mybatis-plus提供的ServiceImpl<M extends BaseMapper<T>, T>类(T表示对应实体类类型),并实现上一步中创建的UserService接口。然后加上@Service注解。

package com.example.service.impl;

import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.example.mapper.UserMapper;
import com.example.pojo.User;
import com.example.service.UserService;
import org.springframework.stereotype.Service;

@Service
public class UserServiceImpl extends ServiceImpl<UserMapper, User> implements UserService {
}

创建好之后项目结构如下:
在这里插入图片描述

至此,虽然我们没有在UserService中内写任何代码,但它已经具备了mybatis-plus提供的基本的CRUD的功能。

Service层的CRUD

save方法

boolean save(T entity); // 插入一条记录
boolean saveBatch(Collection<T> entityList);// 插入(批量),默认分批大小为1000
boolean saveBatch(Collection<T> entityList, int batchSize);// 插入(批量)
public class ServiceCurdTests {
    @Autowired
    UserService userService;
    @Test
    public void testSave(){
        // 创建实体类对象
        User user = new User();
        user.setName("Garrison");
        user.setAge(45);
        user.setEmail("garrsion@gmail.com");
        user.setGender(1);
        //  调用save方法
        userService.save(user);
    }
}

生成的sql语句及输出:

==>  Preparing: INSERT INTO user ( name, age, gender, email ) VALUES ( ?, ?, ?, ? )
==> Parameters: Garrison(String), 45(Integer), 1(Integer), garrsion@gmail.com(String)
<==    Updates: 1

查看数据库,修改成功。
在这里插入图片描述

saveOrUpdate方法

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

saveOrUpdate测试1:

    @Test
    public void testSaveOrUpdate(){
        User user = new User();
        user.setId(7);
        user.setAge(1);
        userService.saveOrUpdate(user);
    }

生成的Sql代码:

==>  Preparing: SELECT id,name,age,gender,email FROM user WHERE id=?
==> Parameters: 7(Integer)
<==      Total: 1
==>  Preparing: UPDATE user SET age=? WHERE id=?
==> Parameters: 1(Integer), 7(Integer)
<==    Updates: 1

saveOrUpdate测试2:

    @Test
    public void testSaveOrUpdate1(){
        User user = new User();
        user.setId(8);
        user.setAge(1);
        userService.saveOrUpdate(user);
    }

生成的sql代码:

==>  Preparing: SELECT id,name,age,gender,email FROM user WHERE id=?
==> Parameters: 8(Integer)
<==      Total: 0
==>  Preparing: INSERT INTO user ( age ) VALUES ( ? )
==> Parameters: 1(Integer)
<==    Updates: 1

通过上面两个测试可以看出:updateOrSave方法会先运行一个Select语句,通过主键字段判断该条记录是否存在,若存在则运行Update语句,否则运行Insert语句,且实体类中为null的属性,不会更新。

remove方法

boolean remove(Wrapper<T> queryWrapper);// 根据 entity 条件,删除记录
boolean removeById(Serializable id); // 根据 ID 删除
boolean removeByMap(Map<String, Object> columnMap);// 根据 columnMap 条件,删除记录
boolean removeByIds(Collection<? extends Serializable> idList);// 删除(根据ID 批量删除)

update方法

boolean update(Wrapper<T> updateWrapper);// 根据 UpdateWrapper 条件,更新记录 需要设置sqlset
boolean update(T updateEntity, Wrapper<T> whereWrapper);// 根据 whereWrapper 条件,更新记录
boolean updateById(T entity);// 根据 ID 选择修改
boolean updateBatchById(Collection<T> entityList);// 根据ID 批量更新
boolean updateBatchById(Collection<T> entityList, int batchSize);// 根据ID 批量更新
    @Test
    public void update(){
        User user = new User();
        user.setName("Hailie");
        user.setAge(32);
        user.setGender(0);
        user.setEmail("haile@gmail.com");
        // 第一个参数实体类对象中的值将会生成对应的set子句
        userService.update(user,new UpdateWrapper<User>().eq("id",8));
    }

生成的sql:

==>  Preparing: UPDATE user SET name=?, age=?, gender=?, email=? WHERE (id = ?)
==> Parameters: Hailie(String), 32(Integer), 0(Integer), haile@gmail.com(String), 8(Integer)
<==    Updates: 1

查看数据库,修改成功。
在这里插入图片描述

一个奇奇怪怪的问题

假设我们使用boolean update(T updateEntity, Wrapper<T> whereWrapper)方法时,在第二个参数中使用UpdateWrappper且设置set与第一个实体类对象中参数冲突会怎么样呢?

本例只是本人学习过程中的突发奇想[doge]…高危代码…请勿模仿…[doge]

    @Test
    public void update01(){
        User user = new User();
        //在此设置年龄为30
        user.setAge(30);
        // 在第二个参数中设置年龄为29
        userService.update(user,new UpdateWrapper<User>().eq("id",8).set("age",29));
    }

生成的sql代码:

==>  Preparing: UPDATE user SET age=?, age=? WHERE (id = ?)
==> Parameters: 30(Integer), 29(Integer), 8(Integer)
<==    Updates: 1

还是可以成功运行,不过生成的sql语句中age被设置了两次,由于age=29在后面,所以最后数据库中的结果是29.

Get方法

根据条件查询一条记录

T getById(Serializable id);// 根据 ID 查询
T getOne(Wrapper<T> queryWrapper);// 根据 Wrapper,查询一条记录。结果集,如果是多个会抛出异常,随机取一条加上限制条件 wrapper.last("LIMIT 1")
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);// 根据 Wrapper,查询一条记录

List方法

根据条件查询多条记录

List<T> list();// 查询所有
List<T> list(Wrapper<T> queryWrapper);// 查询列表
Collection<T> listByIds(Collection<? extends Serializable> idList);// 查询(根据ID 批量查询)
Collection<T> listByMap(Map<String, Object> columnMap);// 查询(根据 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);// 查询全部记录
List<Object> listObjs(Wrapper<T> queryWrapper);// 根据 Wrapper 条件,查询全部记录
<V> List<V> listObjs(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);// 根据 Wrapper 条件,查询全部记录

Page方法

请阅读~~<<mybatis-plus分页功能>>~~

Count方法

int count();// 查询总记录数
int count(Wrapper<T> queryWrapper);// 根据 Wrapper 条件,查询总记录数
@Test
public void testCount(){
    int total = userService.count();
    int male = userService.count(new QueryWrapper<User>().eq("gender",1));
    int female = userService.count(new QueryWrapper<User>().eq("gender", 0));
    System.out.println(String.format("用户总数: %d\n其中:\n\t男性:\t%d\n\t女性:\t%d",
                                     total,male,female));
}

生成的sql语句及输出

==>  Preparing: SELECT COUNT( 1 ) FROM user WHERE (gender = ?)
==> Parameters: 0(Integer)
<==      Total: 1
用户总数: 8
其中:
	男性:	5
	女性:	3

链式查询与链式更新

@Test
public void testChainQuery(){
	QueryChainWrapper<User> query = new QueryChainWrapper<>(userMapper);
	// 查询所有男性用户的id、name和age
	List<User> users = query.select("id", "name", "age").eq("gender",0).list();
	for (User user : users) {
		System.out.println(user);
	}
}

生成的sql语句及输出:

@Test
public void testChainUpdate(){
    UpdateChainWrapper<User> query = new UpdateChainWrapper<>(userMapper);
    // 使所有女性用户年龄增加1
    query.setSql("age = age+1").eq("gender",1).update();
}

生成的sql语句:

==>  Preparing: UPDATE user SET age = age+1 WHERE (gender = ?)
==> Parameters: 1(Integer)
<==    Updates: 5

上一篇:MyBatisPlus Mapper层的CRUD
下一篇:MyBatisPlus提供的分页功能

- THE END -

版权声明:本文为qq_44525150原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。