mybatis-plus-mapper
本文与官网大多数一致,只是在示例中加入了一些实际验证的代码,日志可能和与官网略有出入(预估是因为版本原因)
本文测试代码中mybatis-plus依赖:
<dependency>
<groupId>com.baomidou</groupId>
<artifactId>mybatis-plus-spring-boot3-starter</artifactId>
<version>3.5.7</version>
</dependency>
测试数据
create table user
(
id INT AUTO_INCREMENT PRIMARY KEY NOT NULL,
username CHAR(10) UNIQUE NOT NULL,
age INT,
gender INT,
email VARCHAR(32),
phone_number VARCHAR(32)
);
INSERT INTO user(username, age, gender, email, phone_number)
values ('张三', 22, 1, 'zhangsan@email.com', '1890000001'),
('李四', 21, 1, 'lisi@email.com', '1890000002'),
('王五', 23, 1, 'wangwu@email.com', '1890000003'),
('王小红', 22, 0, 'wangxiaohong@email.com', '1890000004'),
('王麻子', 20, 1, 'wangmazi@email.com', '1890000005'),
('李小雨', 20, 0, 'lixiaoyu@email.com', '1890000007');
概述
BaseMapper 是 Mybatis-Plus 提供的一个通用 Mapper 接口,它封装了一系列常用的数据库操作方法,包括增、删、改、查等。通过继承 BaseMapper,开发者可以快速地对数据库进行操作,而无需编写繁琐的 SQL 语句。
注意:
- 泛型 T 为任意实体对象
- 参数 Serializable 为任意类型主键 Mybatis-Plus 不推荐使用复合主键约定每一张表都有自己的唯一 id 主键
- 对象 Wrapper 为 条件构造器
insert
insert 常用函数定义
// 插入一条记录
int insert(T entity);
- 功能描述: 插入一条记录。
- 返回值: int,表示插入操作影响的行数,通常为 1,表示插入成功。
参数说明:
类型 | 参数名 | 描述 |
---|---|---|
T | entity | 实体对象 |
insert 示例代码
/*************************************************************************/
@Test
public void testInsert() {
UserPO userPO = new UserPO();
userPO.setUsername("王小二");
userPO.setAge(12);
userPO.setGender(1);
userPO.setEmail("177xxx@qq.com");
userMapper.insert(userPO);
}
// => Preparing: INSERT INTO user ( username, age, gender, email ) VALUES ( ?, ?, ?, ? )
// ==> Parameters: 王小二(String), 12(Integer), 1(Integer), 177xxx@qq.com(String)
// <== Updates: 1
delete
delete 常用函数定义
// 根据 entity 条件,删除记录
int delete(@Param(Constants.WRAPPER) Wrapper<T> wrapper);
// 删除(根据ID 批量删除)(已过时,使用下面的函数)
int deleteBatchIds(@Param(Constants.COLLECTION) Collection<? extends Serializable> idList);
// 删除(根据ID 批量删除)
int deleteByIds(@Param(Constants.COLL) Collection<?> idList)
// 根据 ID 删除
int deleteByIds(Serializable id);
// 根据 columnMap 条件,删除记录
int deleteByMap(@Param(Constants.COLUMN_MAP) Map<String, Object> columnMap);
- 功能描述: 删除符合条件的记录。
- 返回值: int,表示删除操作影响的行数,通常为 1,表示删除成功。
参数说明:
类型 | 参数名 | 描述 |
---|---|---|
Wrapper<T> | wrapper | 实体对象封装操作类(可以为 null) |
Collection<? extends Serializable> | idList | 主键 ID 列表(不能为 null 以及 empty) |
Serializable | id | 主键 ID |
Map<String, Object> | columnMap | 表字段 map 对象 |
delete 示例
/*************************************************************************/
@Test
public void testDelete() {
QueryWrapper<UserPO> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("username","张三");
val delete = userMapper.delete(queryWrapper);
log.info("delete :{}",delete);
}
// ==> Preparing: DELETE FROM user WHERE (username = ?)
// ==> Parameters: 张三(String)
// <== Updates: 1
/*************************************************************************/
@Test
public void testDelete2() {
val delete = userMapper.deleteByIds(Arrays.asList(1,2,3));
log.info("delete :{}",delete);
}
// ==> Preparing: DELETE FROM user WHERE id IN ( ? , ? , ? )
// ==> Parameters: 1(Integer), 2(Integer), 3(Integer)
// <== Updates: 2
/*************************************************************************/
@Test
public void testDelete3() {
Map<String,Object> deleteWrapper=new HashMap<>();
deleteWrapper.put("username","李小雨");
deleteWrapper.put("age",26);
val delete = userMapper.deleteByMap(deleteWrapper);
log.info("delete :{}",delete);
}
// ==> Preparing: DELETE FROM user WHERE (age = ? AND username = ?)
// ==> Parameters: 26(Integer), 李小雨(String)
// <== Updates: 0
/*************************************************************************/
update
update 常用函数定义
// 根据 Wrapper 更新记录
// 此方法无法进行自动填充,如需自动填充请使用update(Object, Wrapper)
int update(@Param(Constants.WRAPPER) Wrapper<T> updateWrapper)
// 根据 whereWrapper 条件,更新记录
int update(@Param(Constants.ENTITY) T updateEntity, @Param(Constants.WRAPPER) Wrapper<T> whereWrapper);
// 根据 ID 修改
int updateById(@Param(Constants.ENTITY) T entity);
- 功能描述: 更新符合条件的记录。
- 返回值: int,表示更新操作影响的行数,通常为 1,表示更新成功。
参数说明:
类型 | 参数名 | 描述 |
---|---|---|
T | entity | 实体对象 (set 条件值,可为 null) |
Wrapper<T> | updateWrapper | 实体对象封装操作类(可以为 null,里面的 entity 用于生成 where 语句) |
update 示例代码
/*************************************************************************/
@Test
public void testUpdate() {
UpdateWrapper<UserPO> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("username", "张三");
updateWrapper.set("age",12);
val update = userMapper.update(updateWrapper);
log.info("update :{}", update);
}
// ==> Preparing: UPDATE user SET age=? WHERE (username = ?)
// ==> Parameters: 12(Integer), 张三(String)
// <== Updates: 1
//注这里如果不设置set会报错
/*************************************************************************/
@Test
public void testUpdate2() {
UpdateWrapper<UserPO> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("username", "张三");
UserPO userPO=new UserPO();
userPO.setAge(27);
val update = userMapper.update(userPO,updateWrapper);
log.info("update :{}", update);
}
// ==> Preparing: UPDATE user SET age=? WHERE (username = ?)
// ==> Parameters: 27(Integer), 张三(String)
// <== Updates: 1
//注:这里只有字段有值时才会在set中被拼接。也就是说给一个字段set null不会将数据库中这个字段置空
/*************************************************************************/
@Test
public void testUpdateById() {
UserPO userPO=new UserPO();
userPO.setAge(27);
userPO.setEmail(null);
userPO.setId(3);
val update = userMapper.updateById(userPO);
log.info("update :{}", update);
}
// ==> Preparing: UPDATE user SET age=? WHERE id=?
// ==> Parameters: 27(Integer), 3(Integer)
// <== Updates: 1
/*************************************************************************/
select
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);
- 功能描述: 查询符合条件的记录。
- 返回值: 查询结果,可能是实体对象、Map 对象或其他类型。
参数说明
类型 | 参数名 | 描述 |
---|---|---|
Serializable | id | 主键 ID |
Wrapper<T> | queryWrapper | 实体对象封装操作类(可以为 null) |
Collection<? extends Serializable> | idList | 主键 ID 列表(不能为 null 以及 empty) |
Map<String, Object> | columnMap | 表字段 map 对象 |
IPage<T> | page | 分页查询条件(可以为 RowBounds.DEFAULT) |
select 示例
/*************************************************************************/
@Test
public void testSelectById() {
val userPO = userMapper.selectById(1);
log.info("user :{}", userPO);
}
// ==> Preparing: SELECT id,username,age,gender,email,phone_number FROM user WHERE id=?
// ==> Parameters: 1(Integer)
// <== Columns: id, username, age, gender, email, phone_number
// <== Row: 1, 张三, 27, 1, zhangsan@email.com, 1890000001
// <== Total: 1
/*************************************************************************/
@Test
public void testSelectOne() {
QueryWrapper<UserPO> queryWrapper=new QueryWrapper<>();
queryWrapper.eq("username","张三");
val userPO = userMapper.selectOne(queryWrapper);
log.info("user :{}", userPO);
}
// ==> Preparing: SELECT id,username,age,gender,email,phone_number FROM user WHERE (username = ?)
// ==> Parameters: 张三(String)
// <== Columns: id, username, age, gender, email, phone_number
// <== Row: 1, 张三, 22, 1, zhangsan@email.com, 1890000001
// <== Total: 1
//当查询出多条是抛出异常
/*************************************************************************/
@Test
public void testSelectBatchIds() {
val userPO = userMapper.selectBatchIds(Arrays.asList(1,2,3));
log.info("user :{}", userPO);
}
// ==> Preparing: SELECT id,username,age,gender,email,phone_number FROM user WHERE id IN ( ? , ? , ? )
// ==> Parameters: 1(Integer), 2(Integer), 3(Integer)
// <== Columns: id, username, age, gender, email, phone_number
// <== Row: 1, 张三, 22, 1, zhangsan@email.com, 1890000001
// <== Row: 2, 李四, 21, 1, lisi@email.com, 1890000002
// <== Row: 3, 王五, 27, 1, wangwu@email.com, 1890000003
// <== Total: 3
/*************************************************************************/
@Test
public void testSelectList() {
QueryWrapper<UserPO> queryWrapper=new QueryWrapper<>();
queryWrapper.eq("age","20");
val userPO = userMapper.selectList(queryWrapper);
log.info("user :{}", userPO);
}
// ==> Preparing: SELECT id,username,age,gender,email,phone_number FROM user WHERE (age = ?)
// ==> Parameters: 20(String)
// <== Columns: id, username, age, gender, email, phone_number
// <== Row: 5, 王麻子, 20, 1, wangmazi@email.com, 1890000005
// <== Row: 6, 李小雨, 20, 0, lixiaoyu@email.com, 1890000007
// <== Total: 2
/*************************************************************************/
@Test
public void testSelectByMap() {
Map<String,Object> queryWrapper=new HashMap<>();
queryWrapper.put("age",20);
val userPO = userMapper.selectByMap(queryWrapper);
log.info("user :{}", userPO);
}
// ==> Preparing: SELECT id,username,age,gender,email,phone_number FROM user WHERE (age = ?)
// ==> Parameters: 20(Integer)
// <== Columns: id, username, age, gender, email, phone_number
// <== Row: 5, 王麻子, 20, 1, wangmazi@email.com, 1890000005
// <== Row: 6, 李小雨, 20, 0, lixiaoyu@email.com, 1890000007
// <== Total: 2
/*************************************************************************/
@Test
public void testSelectPage() {
IPage<UserPO> page = new Page<>(1, 3);
QueryWrapper<UserPO> queryWrapper=new QueryWrapper<>();
queryWrapper.gt("age","10");
val userPO = userMapper.selectPage(page,queryWrapper);
log.info("user :{}", userPO);
}
// ==> Preparing: SELECT COUNT(*) AS total FROM user WHERE (age > ?)
// ==> Parameters: 10(String)
// <== Columns: total
// <== Row: 6
// <== Total: 1
// ==> Preparing: SELECT id,username,age,gender,email,phone_number FROM user WHERE (age > ?) LIMIT ?
// ==> Parameters: 10(String), 3(Long)
// <== Columns: id, username, age, gender, email, phone_number
// <== Row: 1, 张三, 22, 1, zhangsan@email.com, 1890000001
// <== Row: 2, 李四, 21, 1, lisi@email.com, 1890000002
// <== Row: 3, 王五, 27, 1, wangwu@email.com, 1890000003
// <== Total: 3
//与IService中分页查询一样需要配置MybatisPlusInterceptor
扩展
增加一个自定义的函数
如果在我们业务中发现BaseMapper 中提供的通用函数不足,我们可以通过扩展加一个自定义的通用函数(如果不是通用的,建议使用Mapper.xml,或者注解方式增加)
在mybatis plus 增加一个自定义的函数主要通过继承AbstractMethod函数来实现。
下面我门通过增加一个findOne 函数来说明怎么添加流程
准备添加的函数
T findOne(Serializable id);
-
继承AbstractMethod实现findOne函数
public class FindOne extends AbstractMethod { public FindOne() { //指定findOne函数使用这里的实现 super("findOne"); } /** * @param mapperClass mapper 接口(继承BaseMapper的接口) * @param modelClass mapper 泛型 (继承BaseMapper的接口的泛型类) * @param tableInfo 数据库表反射信息 * @return */ @Override public MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) { /* 执行 SQL ,动态 SQL 参考类 SqlMethod */ val selectSql = new StringBuilder().append("select ") .append(tableInfo.getAllSqlSelect()) .append(" from ") .append(tableInfo.getTableName()) .append(" where ") .append(tableInfo.getKeyColumn()) .append("=") .append("#{") .append(tableInfo.getKeyProperty()) .append("} "); /* mapper 接口方法名一致 */ //configuration:MyBatisConfiguration //languageDriver:MybatisXMLLanguageDriver //创建一个SqlSource,用于保存sql的语句 SqlSource sqlSource = languageDriver.createSqlSource(configuration, selectSql.toString(), modelClass); /** * 注意这里有this.addXXX函数,我们要根据sql类型来选择,因为他里面要将查询到的结果映射到返回类上 * * 这里我们进行的是select sql所有使用this.addSelectMappedxxx */ return this.addSelectMappedStatementForTable(mapperClass, methodName, sqlSource,tableInfo); } }
-
将AbstractMethod实现注入
public class MySqlInjector extends DefaultSqlInjector { private static final Logger log = LoggerFactory.getLogger(MySqlInjector.class); @Override public List<AbstractMethod> getMethodList(Configuration configuration, Class<?> mapperClass, TableInfo tableInfo) { List<AbstractMethod> methodList = super.getMethodList(configuration,mapperClass, tableInfo); //增加自定义方法,将我们自己实现的FindOne添加进去 methodList.add(new FindOne()); return methodList; } }
-
使用
//方式1 // 那个mapper需要就在里面添加即可 public interface UserMapper extends BaseMapper<UserPO> { UserPO findOne(Serializable id); } //方式二 // 增加一个抽象层,继承这个接口的都会有findOne方法 public interface ProBaseMapper<T> extends BaseMapper<T> { /** * 以下为自己自定义 */ T findOne(Serializable id); }
-
测试
@Test public void test() { val userPO = userMapper.findOne(1); log.info("userPO:{}",userPO); } // ==> Preparing: select id,username,age,gender,email,phone_number from user where id=? // ==> Parameters: 1(Integer) // <== Columns: id, username, age, gender, email, phone_number // <== Row: 1, 张三, 22, 1, zhangsan@email.com, 1890000001 // <== Total: 1
可以看到上面日志中的sql也就是我们在FileOne类中拼接的
mybatis plus自带的选配
- com.baomidou.mybatisplus.extension.injector.methods.InsertBatchSomeColumn;
- com.baomidou.mybatisplus.extension.injector.methods.AlwaysUpdateSomeColumnById;
- com.baomidou.mybatisplus.extension.injector.methods.LogicDeleteByIdWithFill;
InsertBatchSomeColumn
构造函数
- public InsertBatchSomeColumn()
- public InsertBatchSomeColumn(Predicate<TableFieldInfo> predicate)
- public InsertBatchSomeColumn(String name, Predicate<TableFieldInfo> predicate)
/**
* 默认方法名
*/
public InsertBatchSomeColumn() {
super("insertBatchSomeColumn");
}
/**
* 默认方法名
*
* @param predicate 字段筛选条件
*/
public InsertBatchSomeColumn(Predicate<TableFieldInfo> predicate) {
super("insertBatchSomeColumn");
this.predicate = predicate;
}
/**
* @param name 方法名
* @param predicate 字段筛选条件
* @since 3.5.0
*/
public InsertBatchSomeColumn(String name, Predicate<TableFieldInfo> predicate) {
super(name);
this.predicate = predicate;
}
通过上面的构造函数实现可以看出来默认函数名为insertBatchSomeColumn,也可以使用InsertBatchSomeColumn(String name, Predicate<TableFieldInfo> predicate)构造函数来自定义这个函数名称
参数说明
- name:函数名称
- predicate:字段筛选条件,predicate中有一个test函数返回true标识插入时插入这个字段,返回false标识插入时忽略这个字段
使用示例
//这个是bean定义,注意email上添加了 @TableField(fill = FieldFill.UPDATE)
@Data
@TableName("user")
public class UserPO implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
private String username;
private Integer age;
private Integer gender;
@TableField(fill = FieldFill.UPDATE)
private String email;
private String phoneNumber;
}
//1. 将InsertBatchSomeColumn注入
public class MySqlInjector extends DefaultSqlInjector {
@Override
public List<AbstractMethod> getMethodList(Configuration configuration, Class<?> mapperClass, TableInfo tableInfo) {
List<AbstractMethod> methodList = super.getMethodList(configuration,mapperClass, tableInfo);
methodList.add(new InsertBatchSomeColumn(it->{//it中是一个字段的信息
//设置过滤条件
//当对应表中字段有注解@TableField(fill = FieldFill.UPDATE)时,使用insertBatchSomeColumn插入,这个字段不会被插入
return it.getFieldFill()!=FieldFill.UPDATE;
}));
return methodList;
}
}
//添加insertBatchSomeColumn
public interface UserMapper extends BaseMapper<UserPO> {
//添加insertBatchSomeColumn函数
int insertBatchSomeColumn(List<UserPO> entityList);
}
//测试
// ==> Preparing: INSERT INTO user (username,age,gender,phone_number) VALUES (?,?,?,?) , (?,?,?,?)
// ==> Parameters: 5000(String), 12(Integer), 1(Integer), null, 5001(String), 12(Integer), 1(Integer), null
// <== Updates: 2
//可以看到它生成的函数中忽略了email字段
AlwaysUpdateSomeColumnById
- 功能:用于在更新操作时,无论实体对象的某些字段是否有变化,都会强制更新这些字段。这在某些业务场景下非常有用,比如更新时间戳字段,确保每次更新操作都会更新该字段。
- 使用场景:当你需要在每次更新记录时,都更新某些特定的字段(如更新时间、版本号等),即使这些字段在实体对象中没有变化。
构造函数
public AlwaysUpdateSomeColumnById(String name, Predicate<TableFieldInfo> predicate) {
super(name);
this.predicate = predicate;
}
public AlwaysUpdateSomeColumnById() {
super("alwaysUpdateSomeColumnById");
}
/**
* @param predicate 筛选条件
*/
public AlwaysUpdateSomeColumnById(Predicate<TableFieldInfo> predicate) {
super("alwaysUpdateSomeColumnById");
this.predicate = predicate;
}
通过构造函数可以出来:
- 它对应的默认函数名称是alwaysUpdateSomeColumnById
- 它可以设置一个筛选条件
看起来和InsertBatchSomeColumn使用方式差不错,只是功能不一样
使用示例
//这个是bean定义 //这个是bean定义 注意email上添加了 @TableField(fill = FieldFill.UPDATE)
@Data
@TableName("user")
public class UserPO implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
private String username;
private Integer age;
private Integer gender;
@TableField(fill = FieldFill.UPDATE)
private String email;
private String phoneNumber;
}
//1. 将AlwaysUpdateSomeColumnById注入
@Override
public List<AbstractMethod> getMethodList(Configuration configuration, Class<?> mapperClass, TableInfo tableInfo) {
List<AbstractMethod> methodList = super.getMethodList(configuration,mapperClass, tableInfo);
methodList.add(new AlwaysUpdateSomeColumnById(it->{
//当字段上面有FieldFill.UPDATE;才更新,(可以根据自己的实际业务在这里写筛选规则)
return it.getFieldFill()==FieldFill.UPDATE;
}));
return methodList;
}
//2. 添加alwaysUpdateSomeColumnById函数
public interface UserMapper extends BaseMapper<UserPO> {
//加入alwaysUpdateSomeColumnById函数
int alwaysUpdateSomeColumnById(@Param(Constants.ENTITY) UserPO entity);
}
//3. 添加函数
public interface UserMapper extends BaseMapper<UserPO> {
int alwaysUpdateSomeColumnById(UserPO entity);
}
//测试
@Test
public void testAlwaysUpdateSomeColumnById() {
UserPO userPO = new UserPO();
userPO.setId(1);
userPO.setAge(33);
userPO.setEmail("xxxx");
userMapper.alwaysUpdateSomeColumnById(userPO);
}
// ==> Preparing: UPDATE user SET email=? WHERE id=?
// ==> Parameters: xxxx(String), 1(Integer)
// <== Updates: 1
//日志可以看出来没有更新age
关于AlwaysUpdateSomeColumnById的几个问题
- AlwaysUpdateSomeColumnById中设置可过滤规则可能会使@TableField中updateStrategy配置失效
- AlwaysUpdateSomeColumnById过滤会将所有符合条件的都加入更新中,这时如果对应Bean没有设置值为null就会被更新
LogicDeleteByIdWithFill
- 这个方法用于逻辑删除记录,并填充实体对象中的某些字段。逻辑删除意味着不是真正从数据库中删除记录,而是通过更新某个字段(如 deleted 字段)来标记记录已被删除。
- 使用场景:当你需要实现逻辑删除功能,并且希望在删除操作时自动填充实体对象中的某些字段(如删除时间、删除人等)。
示例代码
@Data
@TableName("user")
public class UserPO implements Serializable {
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO)
private Integer id;
@TableField(updateStrategy = FieldStrategy.NOT_NULL)
private String username;
private Integer age;
private Integer gender;
@TableField(fill = FieldFill.UPDATE)
private String email;
private String phoneNumber;
//当deleteByIdWithFill删除这个记录是state会被设置为0,这条数据实际并不会被删除,如果这个bean中没有TableLogic注解,那么这条记录会被删除
@TableLogic(value="1",delval = "0")
private String state;
}
public class MySqlInjector extends DefaultSqlInjector {
@Override
public List<AbstractMethod> getMethodList(Configuration configuration, Class<?> mapperClass, TableInfo tableInfo) {
List<AbstractMethod> methodList = super.getMethodList(configuration, mapperClass, tableInfo);
methodList.add(new LogicDeleteByIdWithFill());
return methodList;
}
}
@Bean
public MySqlInjector mySqlInjector() {
return new MySqlInjector();
}
public interface UserMapper extends BaseMapper<UserPO> {
int deleteByIdWithFill(UserPO entity);
}
//测试
@Test
public void testDeleteByIdWithFill() {
UserPO userPO = new UserPO();
userPO.setId(1);
userPO.setAge(33);
userPO.setEmail("xxxx");
userMapper.deleteByIdWithFill(userPO);
}
// ==> Preparing: UPDATE user SET email=?,state='0' WHERE id=? AND state='1'
// ==> Parameters: xxxx(String), 1(Integer)
// <== Updates: 0
//恶意看出来这个删除执行的是更新操作
//1. 将TableLogic标记的修改为设置的数值
//2. 将设置du数值进行覆盖
通过使用这些选装件,可以进一步扩展 Mybatis-Plus 的功能,满足更多样化的业务需求。
评论区