上一章节介绍了 MP 和 Springboot 的整合,以及 代码生成 的特性。本章节介绍 MP 对 CRUD 的封装,并结合大量 使用示例 帮助理解
MP 帮我们封装了 IService 和 BaseMapper,封装了全面完善的 CRUD 方法,因为我们在继承上述接口后便可以使用这些方法,无须再自己声明
public class QueryWrapper<T> extends AbstractWrapper<T, String, QueryWrapper<T>> implements Query<QueryWrapper<T>, T, String> {
private SharedString sqlSelect;
public QueryWrapper() {
this((Object)null);
}
public QueryWrapper(T entity) {
this.sqlSelect = new SharedString();
super.setEntity(entity);
super.initNeed();
}
public QueryWrapper(T entity, String... columns) {
this.sqlSelect = new SharedString();
super.setEntity(entity);
super.initNeed();
this.select(columns);
}
// 略
}
查询条件 的封装,构造方法可以传入 查询条件 封装 entity
和查询字段 columns
维护 sqlSelect
public class UpdateWrapper<T> extends AbstractWrapper<T, String, UpdateWrapper<T>> implements Update<UpdateWrapper<T>, String> {
// sqlSet,更新时需要指定 setSql 语句
private final List<String> sqlSet;
public UpdateWrapper() {
this((Object)null);
}
public UpdateWrapper(T entity) {
super.setEntity(entity);
super.initNeed();
this.sqlSet = new ArrayList();
}
// 略
}
更新条件 的封装,构造方法可以传入 更新条件 实体 entity
,sqlSet
可维护对应的 set sql
语句
IService,即对 service
层的抽象,排除需要在 service
处理大量其他逻辑的类,简单的 CRUD 完全可以直接使用 IService 定义的方法,比如 save saveOrUpdate get
等
// 单个保存
default boolean save(T entity) {
return SqlHelper.retBool(this.getBaseMapper().insert(entity));
}
// 批量保存
@Transactional(
rollbackFor = {Exception.class}
)
default boolean saveBatch(Collection<T> entityList) {
return this.saveBatch(entityList, 1000);
}
boolean saveBatch(Collection<T> entityList, int batchSize);
示例 demo
@Test
public void testSave() {
// save
Assert.assertTrue(userService.save(new User("1", 1, "1")));
// 批量 save
Assert.assertTrue(userService.saveBatch(new ArrayList<User>() {
{
add(new User("1", 1, "1"));
add(new User("1", 1, "1"));
}
}));
}
default T getById(Serializable id) {
return this.getBaseMapper().selectById(id);
}
default T getOne(Wrapper<T> queryWrapper) {
return this.getOne(queryWrapper, true);
}
// 根据 wrapper 查询一个
// 结果超过一个则抛出异常,默认 true
T getOne(Wrapper<T> queryWrapper, boolean throwEx);
// 根据 wrapper 查询一个 映射为 map
Map<String, Object> getMap(Wrapper<T> queryWrapper);
// 根据 wrapper 查询一个 自定义 Function 映射
<V> V getObj(Wrapper<T> queryWrapper, Function<? super Object, V> mapper);
以 get
前缀的这些方法都是获取单个结果集,示例 demo
@Test
public void testGet() {
// getById
User user = userService.getById(7);
Assert.assertNotNull(user);
// getOne
Assert.assertNotNull(userService.getOne(
new QueryWrapper<>(new User("1", 1, "1"))
// 我们可以 wapper.last(" LIMIT 1") 限制只取一条
.last(" LIMIT 1"),
// 也可以指定的第二个参数为 false,结果超过一条时不抛出异常
false)
);
// getMap
// 结果: name:1
userService.getMap(
new QueryWrapper<>(new User("1", 1, "1"),
"name")
).forEach((k, v) -> System.out.println(k +":"+ v));
// getObj
// 结果;1
System.out.println(userService.getObj(
new QueryWrapper<>(new User("1", 1, "1"),
"name"),
Function.identity()
));
}
// 根据 id 获取列表,一般应该用不到
default List<T> listByIds(Collection<? extends Serializable> idList) {
return this.getBaseMapper().selectBatchIds(idList);
}
// 根据 columnMap 获取列表
default List<T> listByMap(Map<String, Object> columnMap) {
return this.getBaseMapper().selectByMap(columnMap);
}
// 根据 queryWrapper 获取列表
default List<T> list(Wrapper<T> queryWrapper) {
return this.getBaseMapper().selectList(queryWrapper);
}
// emptyWrapper,查询所有
default List<T> list() {
return this.list(Wrappers.emptyWrapper());
}
// 映射为 Map
default List<Map<String, Object>> listMaps(Wrapper<T> queryWrapper) {
return this.getBaseMapper().selectMaps(queryWrapper);
}
default List<Map<String, Object>> listMaps() {
return this.listMaps(Wrappers.emptyWrapper());
}
// Function.identity() 映射
default List<Object> listObjs() {
return this.listObjs(Function.identity());
}
// 自定义映射
default <V> List<V> listObjs(Function<? super Object, V> mapper) {
return this.listObjs(Wrappers.emptyWrapper(), mapper);
}
default List<Object> listObjs(Wrapper<T> queryWrapper) {
return this.listObjs(queryWrapper, Function.identity());
}
default <V> List<V> listObjs(Wrapper<T> queryWrapper, Function<? super Object, V> mapper) {
return (List)this.getBaseMapper().selectObjs(queryWrapper).stream().filter(Objects::nonNull).map(mapper).collect(Collectors.toList());
}
与 get
对应的,以 list
的前缀的方法都是获取多个结果集。方法虽多,但主要都是 queryWrapper
和 mapper
的排列组合,结合部分示例 demo 理解
@Test
public void testList() {
// 根据 map 条件过滤
Assert.assertEquals(3, userService.listByMap(
new HashMap<String, Object>() {
{
put("name", "1");
}
}
).size());
// 查询所有
Assert.assertEquals(3, userService.list().size());
// 以 QueryWrapper 过滤
// 默认 Function.identity() 映射
userService.listObjs(
new QueryWrapper<>(new User("1", null, null))
).forEach(System.out::println);
}
// 根据 id 更新
default boolean updateById(T entity) {
return SqlHelper.retBool(this.getBaseMapper().updateById(entity));
}
// updateWrapper.entity 定义 where 条件
// updateWrapper.setSql 定义 sqlSet
default boolean update(Wrapper<T> updateWrapper) {
return this.update((Object)null, updateWrapper);
}
// updateWrapper.entity 定义 where 条件
// T entity 定义 sqlSet
default boolean update(T entity, Wrapper<T> updateWrapper) {
return SqlHelper.retBool(this.getBaseMapper().update(entity, updateWrapper));
}
// 批量更新
@Transactional(
rollbackFor = {Exception.class}
)
default boolean updateBatchById(Collection<T> entityList) {
return this.updateBatchById(entityList, 1000);
}
boolean updateBatchById(Collection<T> entityList, int batchSize);
示例 demo
@Test
public void testUpdate() {
User u7 = userService.getById(7);
User u8 = userService.getById(8);
// 单个修改
u7.setName("u1");
Assert.assertTrue(userService.updateById(u7));
// 批量修改
u7.setName("u2");
u8.setName("u2");
Assert.assertTrue(userService.updateBatchById(new ArrayList<User>(){
{
add(u7);
add(u8);
}
}));
// UpdateWrapper 必须设置 sqlSet
// 即 entity(u7) 定义 where,sqlSet 定义 set
Assert.assertTrue(
userService.update(
new UpdateWrapper<>(u7)
.setSql("name = 'u3'")
.setSql("age = 3")
)
);
// entity(new User) 定义 where,paramEntity(u7) 定义 set
Assert.assertTrue(
userService.update(u7,
new UpdateWrapper<>(new User("1", null, null))
)
);
}
default boolean saveOrUpdateBatch(Collection<T> entityList) {
return this.saveOrUpdateBatch(entityList, 1000);
}
// 批量 saveOrUpdate
boolean saveOrUpdateBatch(Collection<T> entityList, int batchSize);
boolean saveOrUpdate(T entity);
// 先更新,失败则 saveOrUpdate
default boolean saveOrUpdate(T entity, Wrapper<T> updateWrapper) {
return this.update(entity, updateWrapper) || this.saveOrUpdate(entity);
}
示例 demo
@Test
public void testSaveOrUpdate() {
User u7 = userService.getById(7);
// 单个 saveOrUpdate
u7.setName("sou1");
Assert.assertTrue(userService.saveOrUpdate(u7));
// 批量 saveOrUpdate,其中 u7 update, u save
u7.setName("sou2");
Assert.assertTrue(userService.saveOrUpdateBatch(new ArrayList<User>() {
{
add(u7);
User u = new User("sou2", 4, "sou2");
add(u);
}
}));
// 先执行 update(u7, updateWrapper) u7 定义 sqlSet, new User 定义 where
// 如果执行失败,则 saveOrUpdate(u7)
u7.setName("sou4");
Assert.assertTrue(userService.saveOrUpdate(
u7,
new UpdateWrapper<>(new User("sou2", null, null))
// new UpdateWrapper<>(new User("AnOther", null, null))
));
}
default boolean removeById(Serializable id) {
return SqlHelper.retBool(this.getBaseMapper().deleteById(id));
}
default boolean removeByMap(Map<String, Object> columnMap) {
Assert.notEmpty(columnMap, "error: columnMap must not be empty", new Object[0]);
return SqlHelper.retBool(this.getBaseMapper().deleteByMap(columnMap));
}
default boolean remove(Wrapper<T> queryWrapper) {
return SqlHelper.retBool(this.getBaseMapper().delete(queryWrapper));
}
default boolean removeByIds(Collection<? extends Serializable> idList) {
return CollectionUtils.isEmpty(idList) ? false : SqlHelper.retBool(this.getBaseMapper().deleteBatchIds(idList));
}
示例 demo
@Test
public void testRemove() {
// 根据 id 删除
Assert.assertTrue(userService.removeById(9));
// 批量删除,不存在的无视
Assert.assertTrue(userService.removeByIds(new ArrayList<Integer>() {
{
add(8);
add(9);
}
}));
// QueryWrapper.entity 定义 where 条件
Assert.assertTrue(userService.remove(
new QueryWrapper<>(
new User("sou4", null, null)
)
));
// Map 定义 where 条件
Assert.assertTrue(userService.removeByMap(
new HashMap<String, Object>() {
{
put("name", "1");
}
}
));
}
// 不带条件,查所有
default int count() {
return this.count(Wrappers.emptyWrapper());
}
// 条件过滤
default int count(Wrapper<T> queryWrapper) {
return SqlHelper.retCount(this.getBaseMapper().selectCount(queryWrapper));
}
示例 demo
@Test
public void testCount() {
Assert.assertEquals(3,
userService.count(new QueryWrapper<>(new User("1", null, null))));
}
// 普通 链式 查询
default QueryChainWrapper<T> query() {
return ChainWrappers.queryChain(this.getBaseMapper());
}
// lambda 链式查询
default LambdaQueryChainWrapper<T> lambdaQuery() {
return ChainWrappers.lambdaQueryChain(this.getBaseMapper());
}
// 普通 链式 更新
default UpdateChainWrapper<T> update() {
return ChainWrappers.updateChain(this.getBaseMapper());
}
// lambda 链式更新
default LambdaUpdateChainWrapper<T> lambdaUpdate() {
return ChainWrappers.lambdaUpdateChain(this.getBaseMapper());
}
MP 支持链式的 查询更新 操作,以及更加优雅的 lambda 风格的 链式调用
示例 demo
@Test
public void testChain() {
// 普通链式查询
userService.query()
.eq("name", "1")
.select("id")
.list()
.forEach(System.out::println);
// lambda 链式查询
userService.lambdaQuery()
.eq(User::getName, "1")
.select(User::getId)
.list()
.forEach(System.out::println);
// 普通链式更新
userService.update()
.eq("name", "1")
.update(new User("2", 2, "2"));
// 普通链式更新
userService.update()
.eq("name", "2")
.setSql("name = 3")
.update();
// lambda 链式更新
userService.lambdaUpdate()
.eq(User::getName, "3")
.remove();
}
对应地,BaseMapper 即对 Mapper 层 CRUD 的封装,IService 很多方法的 默认实现 都是基于 BaseMapper ,因此对于 BaseMapper 就不再每个方法一一解读举例了,给出 增删改查 示例 demo
@Test
public void testMapper() {
// 增
Assert.assertEquals(1, userMapper.insert(new User("1", 1, "1")));
// 查
User user = userMapper.selectList(
new QueryWrapper<>(new User("1", null, null))
).get(0);
System.out.println(user);
// 改
Assert.assertEquals(1,
userMapper.update(
user,
new QueryWrapper<>(new User("u2", null, null))
)
);
// 删
System.out.println(userMapper.delete(
new QueryWrapper<>(new User("1", null, null))
));
}
本章节介绍 MP 对 CRUD 的封装,提供了常用的 CRUD 以及更优雅的 链式调用 等,使得我们对 mybatis 的使用更加轻便
上一篇:mybatis-plus 1 —— 整合 Springboot、代码自动生成
下一篇:mybatis-plus 3 条件构造器