Mybatis-Plus:通用CRUD操作
Posted 丿涛哥哥
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Mybatis-Plus:通用CRUD操作相关的知识,希望对你有一定的参考价值。
Mybatis-Plus通⽤CRUD
通过继承BaseMapper来获取到各种各样的单表操作,下面通过案例来演示这些操作。
1、插⼊操作
⽅法定义
/**
* 插⼊⼀条记录
*
* @param entity 实体对象.
*/
int insert(T entity);
测试⽤例
@RunWith(SpringRunner.class)
@SpringBootTest
class MybatisPlusSpringbootApplicationTests
@Autowired
private UserMapper userMapper;
/*
测试添加
*/
@Test
public void testInsert()
User user = new User();
user.setName("小七");
user.setAge("18");
user.setEmail("xiaoqi@163.com");
//返回值是数据库中影响的行数
int result = userMapper.insert(user);
System.out.println(result);
System.out.println("id值为:" + user.getId());
测试结果:
1
id值为:1548196585471504386
可以看到,数据已经写⼊到了数据库,但是id的值是不正确的,或者说不是我们想要的,我们期望的是数据库⾃增⻓,实际是MP⽣成了id的值写⼊到了数据库。
如何设置id的⽣成策略呢?
MP⽀持的id策略:
package com.baomidou.mybatisplus.annotation;
import lombok.Getter;
/**
* ⽣成ID类型枚举类
*
* @author hubin
* @since 2015-11-10
*/
@Getter
public enum IdType
/**
* 数据库ID⾃增
*/
AUTO(0),
/**
* 该类型为未设置主键类型
*/
NONE(1),
/**
* ⽤户输⼊ID
* <p>该类型可以通过⾃⼰注册⾃动填充插件进⾏填充</p>
*/
INPUT(2),
/* 以下3种类型、只有当插⼊对象ID 为空,才⾃动填充。 */
/**
* 全局唯⼀ID (idWorker)
*/
ID_WORKER(3),
/**
* 全局唯⼀ID (UUID)
*/
UUID(4),
/**
* 字符串全局唯⼀ID (idWorker 的字符串表示)
*/
ID_WORKER_STR(5);
private final int key;
IdType(int key)
this.key = key;
修改User对象:
@Data
@NoArgsConstructor
@AllArgsConstructor
public class User
@TableId(type = IdType.AUTO) //指定Id的生成策略为自增长
private Long id;
private String name;
private String age;
private String email;
再次执行(数据库表支持自动增长),插入成功:
@TableField
在MP中通过@TableField注解可以指定字段的⼀些属性,常常解决的问题有2个:
- 对象中的属性名和字段名不⼀致的问题(⾮驼峰)
- 对象中的属性字段在表中不存在的问题
使⽤:
其他⽤法,如数据库表中的某一个字段不加⼊查询字段
演示效果:
User(id=1, name=null, age=18, mail=test1@baomidou.com, address=null)
User(id=2, name=null, age=20, mail=test2@baomidou.com, address=null)
User(id=3, name=null, age=28, mail=test3@baomidou.com, address=null)
User(id=4, name=null, age=21, mail=test4@baomidou.com, address=null)
User(id=5, name=null, age=24, mail=test5@baomidou.com, address=null)
2、更新操作
在MP中,更新操作有2种,⼀种是根据id更新,另⼀种是根据条件更新。
2.1、根据id更新
⽅法定义:
/**
* 根据 ID 修改
*
* @param entity 实体对象
*/
int updateById(@Param(Constants.ENTITY) T entity);
编写测试方法:
/*
测试根据ID进行修改
*/
@Test
public void testUpdateById()
User user = new User();
user.setId(6L);
user.setAge("30");
int i = userMapper.updateById(user);
System.out.println(i);
测试结果:
2.2、根据条件更新
⽅法定义:
/**
* 根据 whereEntity 条件,更新记录
*
* @param entity 实体对象 (set 条件值,可以为 null)
* @param updateWrapper 实体对象封装操作类(可以为 null,⾥⾯的 entity ⽤于⽣成 where 语句)
*/
int update(@Param(Constants.ENTITY) T entity, @Param(Constants.WRAPPER) Wrapper<T> updateWrapper);
测试⽤例:
/*
测试根据条件进行修改
*/
@Test
public void testUpdate()
//1. 更新的字段
User user = new User();
user.setAge("35");
//2. 更新的条件
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name","小七");
int i = userMapper.update(user, queryWrapper);
System.out.println(i);
或者,通过UpdateWrapper进⾏更新:
@Test
public void testUpdate2()
UpdateWrapper<User> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("id",6).set("age",40);
int i = userMapper.update(null,updateWrapper);
System.out.println(i);
测试结果:
[main] [com.tao.mapper.UserMapper.update]-[DEBUG] ==> Preparing: UPDATE _user SET age=? WHERE id = ?
[main] [com.tao.mapper.UserMapper.update]-[DEBUG] ==> Parameters: 40(String),6(Integer)
[main] [com.tao.mapper.UserMapper.update]-[DEBUG] <== Updates: 1
两种方式均可达到更新的效果。
3、删除操作
3.1、deleteById
⽅法定义:
/**
* 根据 ID 删除
*
* @param id 主键ID
*/
int deleteById(Serializable id);
测试⽤例:
/*
根据Id进行删除
*/
@Test
public void testDeleteById()
int i = userMapper.deleteById(6L);
System.out.println(i);
结果:
[main] [com.tao.mmapper.UserMapper.deleteById]-[DEBUG] ==> Preparing: DELETE FROM user WHERE id=?
[main] [com.tao.mapper.UserMapper.deleteById]-[DEBUG] ==> Parameters: 6(Long)
[main] [com.tao.mapper.UserMapper.deleteById]-[DEBUG] <== Updates: 1
数据被删除。
3.2、deleteByMap
⽅法定义:
/**
* 根据 columnMap 条件,删除记录
*
* @param columnMap 表字段 map 对象
*/
int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
测试⽤例:
/*
根据columnMap进行删除
*/
@Test
public void testDeleteByMap()
HashMap<String, Object> map = new HashMap<>();
map.put("name","小七");
map.put("age",18);
//将columnMap中的元素设置为删除的条件,多个条件是and关系
int i = userMapper.deleteByMap(map);
System.out.println(i);
结果:
[main] [com.tao.mapper.UserMapper.deleteByMap]-[DEBUG] ==> Preparing: DELETE FROM user WHERE name = ? AND age = ?
[main] [com.tao.mapper.UserMapper.deleteByMap]-[DEBUG] ==> Parameters: 小七(String), 18(Integer)
[main] [com.tao.mapper.UserMapper.deleteByMap]-[DEBUG] <== Updates: 0
3.3、delete
⽅法定义:
/**
* 根据 entity 条件,删除记录
*
* @param wrapper 实体对象封装操作类(可以为 null)
*/
int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);
测试⽤例:
/*
调用delete进行删除
*/
@Test
public void testDelete()
User user = new User();
user.setName("小七1");
user.setAge("18");
//将实体对象进行包装,包装为操作对象
QueryWrapper<User> queryWrapper = new QueryWrapper<>(user);
//queryWrapper.eq("name","小七1").eq("age",18);
int i = userMapper.delete(queryWrapper);
System.out.println(i);
结果:
[main] [com.tao.mapper.UserMapper.delete]-[DEBUG] ==> Preparing: DELETE FROM user WHERE name=? AND age=?
[main] [com.tao.mapper.UserMapper.delete]-[DEBUG] ==> Parameters: 小七1(String),18(Integer)
[main] [com.tao.mapper.UserMapper.delete]-[DEBUG] <== Updates: 0
3.4、deleteBatchIds
⽅法定义:
/**
* 删除(根据ID 批量删除)
*
* @param idList 主键ID列表(不能为 null 以及 empty)
*/
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
测试⽤例:
/*
调用deleteBatchIds进行删除
*/
@Test
public void testDeleteBatchIds()
int i = userMapper.deleteBatchIds(Arrays.asList(10L,11L));
System.out.println(i);
结果:
[main] [com.tao.mapper.UserMapper.deleteBatchIds]-[DEBUG] ==> Preparing: DELETE FROM user WHERE id IN ( ? , ? )
[main] [com.tao.mapper.UserMapper.deleteBatchIds]-[DEBUG] ==> Parameters: 10(Long), 20(Long)
[main] [com.tao.mapper.UserMapper.deleteBatchIds]-[DEBUG] <== Updates: 2
4、查询操作
MP提供了多种查询操作,包括根据id查询、批量查询、查询单条数据、查询列表、分⻚查询等操作。
4.1、selectById
⽅法定义:
/**
* 根据 ID 查询
*
* @param id 主键ID
*/
T selectById(Serializable id);
测试⽤例:
/*
根据Id进行查询
*/
@Test
public void testSelectById()
User user = userMapper.selectById(12L);
System.out.println(user);
结果:
User(id=12, name=小七, age=20, mail=test, address=null)
4.2、selectBatchIds
⽅法定义:
/**
* 查询(根据ID 批量查询)
*
* @param idList 主键ID列表(不能为 null 以及 empty)
*/
List<T> selectBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
测试⽤例:
/*
根据Id进行批量查询
*/
@Test
public void testSelectBatchIds()
List<User> users = userMapper.selectBatchIds(Arrays.asList(6L, 12L));
for (User user : users)
System.out.println(user);
结果:
User(id=6, name=小七1, age=18, mail=xiaoqi@163.com, address=null)
User(id=12, name=小七, age=20, mail=test, address=null)
4.3、selectOne
⽅法定义:
/**
* 根据 entity 条件,查询⼀条记录
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
T selectOne(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper)
测试⽤例:
/*
测试selectOne
*/
@Test
public void testSelectOne()
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("name","小七");
//根据条件查询一条记录,如果查询结果超过一条,会报错
User user = userMapper.selectOne(queryWrapper);
System.out.println(user);
结果:
User(id=12, name=小七, age=20, mail=test, address=null)
4.4、selectCount
⽅法定义:
/**
* 根据 Wrapper 条件,查询总记录数
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
Integer selectCount(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
测试⽤例:
/*
根据wrapper条件,查询总记录数
*/
@Test
public void testSelectCount()
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.gt("age",18); //查询年龄大于18的
Integer count = userMapper.selectCount(queryWrapper);
System.out.println(count);
结果:
5
4.5、selectList
⽅法定义:
/**
* 根据 entity 条件,查询全部记录
*
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
List<T> selectList(@Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
测试⽤例:
/*
根据wrapper条件,查询数据
*/
@Test
public void testSelectList()
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.gt("age",18); //查询年龄大于18的
//根据条件查询数据
List<User> users = userMapper.selectList(queryWrapper);
for (User user : users)
System.out.println(user);
结果:
User(id=2, name=Jack, age=20, mail=test2@baomidou.com, address=null)
User(id=3, name=Tom, age=28, mail=test3@baomidou.com, address=null)
User(id=4, name=Sandy, age=21, mail=test4@baomidou.com, address=null)
User(id=5, name=Billie, age=24, mail=test5@baomidou.com, address=null)
User(id=12, name=小七, age=20, mail=test, address=null)
4.6、selectPage
⽅法定义:
/**
* 根据 entity 条件,查询全部记录(并翻⻚)
*
* @param page 分⻚查询条件(可以为 RowBounds.DEFAULT)
* @param queryWrapper 实体对象封装操作类(可以为 null)
*/
IPage<T> selectPage(IPage<T> page, @Param(Constants.WRAPPER) Wrapper<T> queryWrapper);
配置分⻚插件:
@Configuration
public class MybatisPlusConfig
/*
分页插件
*/
@Bean
public PaginationInterceptor paginationInterceptor()
return new PaginationInterceptor();
测试⽤例:
/*
分页查询
*/
@Test
public void testSelectPage()
QueryWrapper<User> queryWrapper = new QueryWrapper<>();
queryWrapper.gt("age",18); //查询年龄大于18的
//第一个参数:当前页 第二个参数:每页显示条数
Page<User> page = new Page<>(1, 2);
IPage<User> userIPage = userMapper.selectPage(page, queryWrapper);
System.out.println("总条数:" + userIPage.getTotal());
System.out.println("总页数:" + userIPage.getPages());
System.out.println("分页数据:" + userIPage.getRecords());
结果:
总条数:5
总页数:3
分页数据:[User(id=2, name=Jack, age=20, mail=test2@baomidou.com, address=null), User(id=3, name=Tom, age=28, mail=test3@baomidou.com, address=null)]
5、SQL注⼊的原理
在MP中,ISqlInjector负责SQL的注⼊⼯作,它是⼀个接⼝,AbstractSqlInjector是它的实现类,实现关系如下:
在AbstractSqlInjector中,主要是由inspectInject()⽅法进⾏注⼊的,如下:
@Overried
public void inspectInject(MapperBuilderAssistant builderAssistant, Class<?> mapperClass)
Class<?> modelClass = this.extractModelClass(mapperClass);
if (modelClass != null)
String className = mapperClass.toString();
Set<String> mapperRegistryCache = GlobalConfigUtils.getMapperRegistryCache(builderAssistant.getConfiguration());
if (!mapperRegistryCache.contains(className))
List<AbstractMethod> methodList = this.getMethodList();
if (CollectionUtils.isNotEmpty(methodList))
TableInfo tableInfo = TableInfoHelper.initTableInfo(builderAssistant, modelClass);
// 循环注⼊⾃定义⽅法
methodList.forEach((m) ->
m.inject(builderAssistant, mapperClass, modelClass, tableInfo);
);
else
logger.debug(mapperClass.toString() + ", No effective injection method was found.");
mapperRegistryCache.add(className);
在实现⽅法中, methodList.forEach(m -> m.inject(builderAssistant, mapperClass, modelClass, tableInfo));
是关键,循环遍历⽅法,进⾏注⼊。
最终调⽤抽象⽅法injectMappedStatement进⾏真正的注⼊:
/**
* 注⼊⾃定义 MappedStatement
*
* @param mapperClass mapper 接⼝
* @param modelClass mapper 泛型
* @param tableInfo 数据库表反射信息
* @return MappedStatement
*/
publi以上是关于Mybatis-Plus:通用CRUD操作的主要内容,如果未能解决你的问题,请参考以下文章