Mybatis-Plus:持久层数据的高效处理(二)--常用API的测试
🤚我的博客
- 欢迎光临我的博客:
https://blog.csdn.net/qq_52434217?type=blog
🥛前言
上一章快速入门使用了MybatisX生成java代码并初次体验了mapper组件,这一章原本打算介绍一下如何编写自定义sql语句。但为了更清楚的知道MybatisX生成的代码的含义,这一章首先介绍MybatisX生成的代码。
MybatisX生成代码文件的简单解读
🔷前置准备–日志输出
为了方便观察sql语句的执行,这里需要配置一下sql日志的输出
mybatis-plus:
configuration:
log-impl: org.apache.ibatis.logging.stdout.StdOutImpl
运行效果如下图
🔷mapper层相关代码
import com.vinta.my_test.entity.Test1;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* @author VINTA
* @description 针对表【test1】的数据库操作Mapper
* @createDate 2024-02-18 21:17:23
* @Entity com.vinta.my_test.entity.Test1
*/
public interface Test1Mapper extends BaseMapper<Test1> {
}
MybatisX生成的代码是根据数据表表名而定的,如这里的Test1Mapper
对应的数据表是test1
。Test1Mapper
继承自BaseMapper<Test1>
泛型接口。该泛型接口已经实现了简单的CRUD操作,只要继承自BaseMapper
接口后,无需编写 mapper.xml
文件,即可获得CRUD功能。
mapper映射关系
这个xml文件位于resource/mapper
目录下,它是数据表字段与实体类属性的对应关系。暂时只要知道这个xml是数据表与实体类的映射关系即可,后面在讲解自定义mysql语句时会详细解释。
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.vinta.my_test.mapper.Test1Mapper">
<resultMap id="BaseResultMap" type="com.vinta.my_test.entity.Test1">
<id property="id" column="id" jdbcType="INTEGER"/>
<result property="username" column="username" jdbcType="VARCHAR"/>
<result property="password" column="password" jdbcType="VARCHAR"/>
<result property="name" column="name" jdbcType="VARCHAR"/>
<result property="age" column="age" jdbcType="INTEGER"/>
<result property="gender" column="gender" jdbcType="TINYINT"/>
<result property="phone" column="phone" jdbcType="VARCHAR"/>
<result property="email" column="email" jdbcType="VARCHAR"/>
<result property="avatar" column="avatar" jdbcType="VARCHAR"/>
<result property="department" column="department" jdbcType="VARCHAR"/>
<result property="salary" column="salary" jdbcType="DOUBLE"/>
<result property="address" column="address" jdbcType="VARCHAR"/>
<result property="status" column="status" jdbcType="TINYINT"/>
</resultMap>
<sql id="Base_Column_List">
id,username,password,
name,age,gender,
phone,email,avatar,
department,salary,address,
status
</sql>
</mapper>
insert方法
/**
* 插入一条记录
* @param entity 实体对象
*/
int insert(T entity);
delete方法
wrapper
是条件参数,通过wrapper
可以生成对应的sql语句,具体后面专门章节细讲。id
为Serializable
类是因为mybatis底层通过反射实现,反射依赖于接口,而所有的Number
类型都是实现了Serializable
接口。columnMap
传入的key
为列名,value
为条件,具体后面专门章节细讲。
// 根据 entity 条件,删除记录
int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);
// 删除(根据ID 批量删除,这里传入的是id list,非实体类list)
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
// 根据 ID 删除
int deleteById(Serializable id);
// 根据 columnMap 条件,删除记录
int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
Update方法
// 根据 whereWrapper 条件,更新记录
int update(@Param(Constants.ENTITY) T updateEntity,
@Param(Constants.WRAPPER) Wrapper<T> whereWrapper);
// 根据 ID 修改 主键属性必须值
int updateById(@Param(Constants.ENTITY) T entity);
Select方法
// 根据 ID 查询
T selectById(Serializable id);
// 根据 entity 条件,查询一条记录
T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 查询(根据ID 批量查询)
List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
// 根据 entity 条件,查询全部记录
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 查询(根据 columnMap 条件)
List<T> selectByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
// 根据 Wrapper 条件,查询全部记录
List<Map<String, Object>> selectMaps(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录。注意: 只返回第一个字段的值
List<Object> selectObjs(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 entity 条件,查询全部记录(并翻页)
IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询全部记录(并翻页)
IPage<Map<String, Object>> selectMapsPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
// 根据 Wrapper 条件,查询总记录数
Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
🔷service层相关代码
service接口
import com.vinta.my_test.entity.Test1;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* @author VINTA
* @description 针对表【test1】的数据库操作Service
* @createDate 2024-02-18 21:17:23
*/
public interface Test1Service extends IService<Test1> {
}
Test1Service
接口继承自IService
泛型接口,在IService
泛型接口中实现了一半的默认方法。实现了Test1Service
可以直接调用部分CRUD。IService
接口除了实现了默认方法,还添加了事务回滚。因此,在后面自定义service方法时也需要添加事务回滚。
serviceImpl实现类
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.vinta.my_test.entity.Test1;
import com.vinta.my_test.service.Test1Service;
import com.vinta.my_test.mapper.Test1Mapper;
import org.springframework.stereotype.Service;
/**
* @author VINTA
* @description 针对表【test1】的数据库操作Service实现
* @createDate 2024-02-18 21:17:23
*/
@Service
public class Test1ServiceImpl extends ServiceImpl<Test1Mapper, Test1>
implements Test1Service{
}
Test1ServiceImpl
实现类继承自ServiceImpl
泛型类,该泛型类实现了Test1Service
接口的另一半的方法。
save插入接口
保存:
// 插入一条记录(选择字段,策略插入)
boolean save(T entity);
// 插入(批量)
boolean saveBatch(Collection<T> entityList);
// 插入(批量)
boolean saveBatch(Collection<T> entityList, int batchSize);
saveOrUpdate接口
修改或者保存:
// 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);
remove删除接口
移除:
// 根据 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);
update更新接口
更新:
// 根据 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);
查询数量
数量:
// 查询总记录数
int count();
// 根据 Wrapper 条件,查询总记录数
int count(Wrapper<T> queryWrapper);
get查询接口
查询:
// 根据 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);
查询集合
集合:
// 查询所有
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参数和page参数的接口。不论是在service层中还是在mapper层中,操作都是一样的,所以这里只做mapper层的测试。
在测试类中注入组件
import com.vinta.my_test.entity.Test1;
import com.vinta.my_test.mapper.Test1Mapper;
import jakarta.annotation.Resource;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import java.util.*;
@SpringBootTest
class MyTestApplicationTests {
@Resource
private Test1Mapper test1Mapper;
}
根据实体操作
@Test
void insertTest() {
Test1 test1 = new Test1();
test1.setUsername("xiaoye111");
test1.setPassword("123456");
test1.setName("xiaoye");
test1.setAge(18);
test1.setGender(1);
test1.setPhone("12345678901");
test1.setEmail("123@qq.com");
test1.setDepartment("IT");
test1.setSalary(10000.0);
test1.setStatus(1);
test1.setAvatar("123.jpg");
test1.setAddress("湖北省武汉市江夏区");
System.out.println(test1Mapper.insert(test1));
}
// 返回 1
该操作相当于sql语句
INSERT INTO test1 ( username , password , name , age , gender , phone , email , avatar , department , salary , address , status) VALUES("xiaoye111","123456","xiaoye",18,1,"12345678901","123@qq.com","IT",10000.0,1,"123.jpg","湖北省武汉市江夏区");
根据id操作
@Test
void selectTest() {
Integer[] ids = {1, 2, 3, 4, 5, 6};
List<Integer> list = Arrays.asList(ids);
List<Test1> test1s = test1Mapper.selectBatchIds(list);
test1s.forEach(System.out::println);
}
/* Test1 [Hash = 667046708, id=1, username=zhangsan111, password=zhangsan111, name=张三, age=35, gender=1, phone=13512345678, email=13512345678@qq.com, avatar=, department=销售部, salary=15000.0, address=北京市海淀区中关村, status=1, serialVersionUID=1]
Test1 [Hash = -236926384, id=2, username=lisi111, password=lisi111, name=李四, age=28, gender=1, phone=15698765432, email=15698765432@qq.com, avatar=, department=市场营销部, salary=12000.0, address=上海市浦东新区张江, status=1, serialVersionUID=1]
Test1 [Hash = -1715870505, id=3, username=wangwu111, password=wangwu111, name=王五, age=42, gender=1, phone=13811112222, email=13811112222@qq.com, avatar=, department=研发部, salary=20000.0, address=广东省深圳市南山区科技园, status=1, serialVersionUID=1]
Test1 [Hash = 95296361, id=4, username=zhaoliu111, password=zhaoliu111, name=赵六, age=25, gender=0, phone=13933334444, email=13933334444@qq.com, avatar=, department=人力资源部, salary=10000.0, address=江苏省南京市玄武区, status=1, serialVersionUID=1]
Test1 [Hash = 1975952528, id=5, username=liuqi111, password=liuqi111, name=刘七, age=22, gender=0, phone=13655556666, email=13655556666@qq.com, avatar=, department=财务部, salary=18000.0, address=四川省成都市高新区, status=1, serialVersionUID=1]
Test1 [Hash = 1684758064, id=6, username=zhouba111, password=zhouba111, name=周八, age=33, gender=1, phone=15077778888, email=15077778888@qq.com, avatar=, department=操作部, salary=13500.0, address=天津市滨海新区, status=1, serialVersionUID=1]
*/
该操作相当于下面的sql
SELECT id,username,password,name,age,gender,phone,email,avatar,department,salary,address,status FROM test1 WHERE id IN ( 1 , 2 , 3 , 4 , 5 , 6 );
根据map查询
@Test
void testColumnMap(){
Map<String,Object> map = new HashMap<>();
map.put("name","xiaoye");
System.out.println(test1Mapper.selectByMap(map));
}
//[Test1 [Hash = 1585078543, id=8, username=xiaoye111, password=123456, name=xiaoye, age=18, gender=1, phone=12345678901, email=123@qq.com, avatar=123.jpg, department=IT, salary=10000.0, address=湖北省武汉市江夏区, status=1, serialVersionUID=1]]
该操作相当于下面的sql语句
SELECT id,username,password,name,age,gender,phone,email,avatar,department,salary,address,status FROM test1 WHERE name = "xiaoye";
END
至此,本章内容主要介绍了常用的API并进行了测试,下一章继续mapper层的介绍条件查询和分页查询以及service层的条件查询和lambda函数作为条件的查询语句。
公众号
欢迎关注小夜的公众号