侧边栏壁纸
博主头像
爱探索

行动起来,活在当下

  • 累计撰写 42 篇文章
  • 累计创建 11 个标签
  • 累计收到 2 条评论

目 录CONTENT

文章目录

mybatis-plus-mapper

jelly
2024-08-16 / 0 评论 / 0 点赞 / 57 阅读 / 0 字

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,表示插入成功。

参数说明:

类型参数名描述
Tentity实体对象

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)
Serializableid主键 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,表示更新成功。

参数说明:

类型参数名描述
Tentity实体对象 (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 对象或其他类型。

参数说明

类型参数名描述
Serializableid主键 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);

  1. 继承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);
        }
    }
    
    
  2. 将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;
            }
        }
    
    
  3. 使用

    
        //方式1
    
        // 那个mapper需要就在里面添加即可
    
        public interface UserMapper extends BaseMapper<UserPO> {
    
            UserPO findOne(Serializable id);
    
        }
    
        //方式二
        // 增加一个抽象层,继承这个接口的都会有findOne方法
        public interface ProBaseMapper<T> extends BaseMapper<T> {
    
            /**
             * 以下为自己自定义
             */
            T findOne(Serializable id);
        }
    
    
  4. 测试

    
        @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;
    }

通过构造函数可以出来:

  1. 它对应的默认函数名称是alwaysUpdateSomeColumnById
  2. 它可以设置一个筛选条件

看起来和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的几个问题

  1. AlwaysUpdateSomeColumnById中设置可过滤规则可能会使@TableField中updateStrategy配置失效
  2. 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 的功能,满足更多样化的业务需求。

0

评论区