当前位置: 首页 >Java技术 > 如何扩展MybatisPlus的BaseMapper(Sql注入器的使用、自动填充功能、逻辑删除功能)

如何扩展MybatisPlus的BaseMapper(Sql注入器的使用、自动填充功能、逻辑删除功能)

工作中常用的MybatisPlus的扩展功能:Sql注入器的使用、自动填充功能、逻辑删除功能

文章底部有git地址

SQL注入器的使用

我们只用MybatisPlus时,MybatisPlus在BaseMapper中提供了很多可以直接调用的方法,这些方法主要是通过ISqlInjector注入器进行注入,然后并提供使用的,

如果我们也想提供一个公用的方法,就可以通过sql注入器来解决

创建mp_user表

CREATE TABLE `mp_user` (  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键id',  `create_user` varchar(255) DEFAULT NULL COMMENT '创建人',  `create_date` datetime DEFAULT CURRENT_TIMESTAMP COMMENT '创建时间',  `update_user` varchar(255) DEFAULT NULL COMMENT '更新人',  `update_date` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间',  `delete_flag` tinyint(1) unsigned NOT NULL DEFAULT '0' COMMENT '删除标识:0-未删除,1-已删除',  `useame` varchar(50) DEFAULT NULL COMMENT '用户名',  `password` varchar(50) DEFAULT NULL COMMENT '密码',  `birthday` varchar(50) DEFAULT NULL COMMENT '生日',  PRIMARY KEY (`id`)) ENGINE=InnoDB AUTO_INCREMENT=1434793267970568194 DEFAULT CHARSET=utf8;

添加数据

INSERT INTO `test`.`mp_user`(`id`, `create_user`, `create_date`, `update_user`, `update_date`, `delete_flag`, `useame`, `password`, `birthday`) VALUES (1, NULL, NULL, NULL, '2021-09-06 15:51:55', 0, 'lily', '123', '2019-12-12');INSERT INTO `test`.`mp_user`(`id`, `create_user`, `create_date`, `update_user`, `update_date`, `delete_flag`, `useame`, `password`, `birthday`) VALUES (2, NULL, NULL, NULL, '2021-09-06 15:51:56', 0, 'tom', '123', '2019-12-12');

创建User实体

package com.qjc.entity;import com.baomidou.mybatisplus.annotation.*;import lombok.Data;import java.io.Serializable;import java.util.Date;@Data@TableName("mp_user")public class User implements Serializable {private static final long serialVersionUID = 1L;@TableIdprivate Long id;private String createUser;private Date createDate;private String updateUser;private Date updateDate;private Integer deleteFlag;private String useame;private String password;private String birthday;}

定义MyBaseMapper继承BaseMapper

并定义一个mySelectList方法

package com.qjc.mapper;import com.baomidou.mybatisplus.core.conditions.Wrapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;import org.apache.ibatis.annotations.Param;import java.util.List;/** * @ClassName: MyBaseMapper * @Description: * @Author: qjc * @Date: 2021/9/6 12:59 下午 */public interface MyBaseMapper<T> extends BaseMapper {List<T> mySelectList(@Param("ew") Wrapper<T> queryWrapper);}

然后创建注入器MySqlInjector,继承SqlInjector的实现类DefaultSqlInjector

package com.qjc.sqlInjector;import com.baomidou.mybatisplus.core.injector.AbstractMethod;import com.baomidou.mybatisplus.core.injector.DefaultSqlInjector;import java.util.List;/** * @ClassName: MySqlInjector * @Description: * @Author: qjc * @Date: 2021/9/6 1:01 下午 */public class MySqlInjector extends DefaultSqlInjector {@Overridepublic List<AbstractMethod> getMethodList(Class<?> mapperClass) {List<AbstractMethod> methodList = super.getMethodList(mapperClass);methodList.add(new MySelectList());retu methodList;}}

创建该注入器需要将自定义的方法添加到methodList中,所以需要创建一个方法类(可以参照源码中定义的类)

定义方法类MySelectList(和刚才MyBaseMapper中定义的方法名不一致也没关系,这不是重点)

package com.qjc.sqlInjector;import com.baomidou.mybatisplus.core.enums.SqlMethod;import com.baomidou.mybatisplus.core.injector.AbstractMethod;import com.baomidou.mybatisplus.core.metadata.TableInfo;import com.baomidou.mybatisplus.core.toolkit.sql.SqlScriptUtils;import org.apache.ibatis.mapping.MappedStatement;import org.apache.ibatis.mapping.SqlSource;/** * @ClassName: FindAll * @Description: * @Author: qjc * @Date: 2021/9/6 1:02 下午 */public class MySelectList extends AbstractMethod {@Overridepublic MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {//String sqlMethod = "findAll";//String sql = "select * from " + tableInfo.getTableName();//SqlSource sqlSource = this.languageDriver.createSqlSource(this.configuration, sql, modelClass);//retu this.addSelectMappedStatement(mapperClass, sqlMethod, sqlSource, modelClass, tableInfo);SqlMethod sqlMethod = SqlMethod.SELECT_LIST;String sql = String.format(sqlMethod.getSql(), sqlFirst(),sqlSelectColumns(tableInfo, true), tableInfo.getTableName(),sqlWhereEntityWrapper(true, tableInfo), sqlComment());SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);retu this.addSelectMappedStatementForTable(mapperClass, "mySelectList", sqlSource, tableInfo);}@Overridepublic String sqlWhereEntityWrapper(boolean newLine, TableInfo table) {if (table.isLogicDelete()) {String sqlScript = table.getAllSqlWhere(true, true, WRAPPER_ENTITY_DOT);sqlScript = SqlScriptUtils.convertIf(sqlScript, String.format("%s != null", WRAPPER_ENTITY),true);sqlScript += (NEWLINE + table.getLogicDeleteSql(true, true) + NEWLINE);String normalSqlScript = SqlScriptUtils.convertIf(String.format("AND ${%s}", WRAPPER_SQLSEGMENT),String.format("%s != null and %s != '' and %s", WRAPPER_SQLSEGMENT, WRAPPER_SQLSEGMENT,WRAPPER_NONEMPTYOFNORMAL), true);normalSqlScript += NEWLINE;normalSqlScript += SqlScriptUtils.convertIf(String.format(" ${%s}", WRAPPER_SQLSEGMENT),String.format("%s != null and %s != '' and %s", WRAPPER_SQLSEGMENT, WRAPPER_SQLSEGMENT,WRAPPER_EMPTYOFNORMAL), true);sqlScript += normalSqlScript;sqlScript = SqlScriptUtils.convertChoose(String.format("%s != null", WRAPPER), sqlScript,table.getLogicDeleteSql(false, true));sqlScript = SqlScriptUtils.convertWhere(sqlScript);retu newLine ? NEWLINE + sqlScript : sqlScript;} else {String sqlScript = table.getAllSqlWhere(false, true, WRAPPER_ENTITY_DOT);sqlScript = SqlScriptUtils.convertIf(sqlScript, String.format("%s != null", WRAPPER_ENTITY), true);sqlScript += NEWLINE;sqlScript += SqlScriptUtils.convertIf(String.format(SqlScriptUtils.convertIf(" AND", String.format("%s and %s", WRAPPER_NONEMPTYOFENTITY, WRAPPER_NONEMPTYOFNORMAL), false) + " ${%s}", WRAPPER_SQLSEGMENT),String.format("%s != null and %s != '' and %s", WRAPPER_SQLSEGMENT, WRAPPER_SQLSEGMENT,WRAPPER_NONEMPTYOFWHERE), true);sqlScript = SqlScriptUtils.convertWhere(sqlScript) + NEWLINE;sqlScript += SqlScriptUtils.convertIf(String.format(" ${%s}", WRAPPER_SQLSEGMENT),String.format("%s != null and %s != '' and %s", WRAPPER_SQLSEGMENT, WRAPPER_SQLSEGMENT,WRAPPER_EMPTYOFWHERE), true);sqlScript = SqlScriptUtils.convertIf(sqlScript, String.format("%s != null", WRAPPER), true);retu newLine ? NEWLINE + sqlScript : sqlScript;}}}

重写injectMappedStatement方法,来将方法注入到MappedStatement中,需要注意的是addSelectMappedStatement方法第二个参数,

是方法名,及MyBaseMapper中自定义的mySelectList

然后最重要的是sqlWhereEntityWrapper方法,该方法就是定义sql语句的,可在此修改为自己想要的查询语句

让UserMapper继承我们创建的MyBaseMapper

package com.qjc.mapper;import com.baomidou.mybatisplus.core.conditions.Wrapper;import com.baomidou.mybatisplus.core.mapper.BaseMapper;import org.apache.ibatis.annotations.Param;import java.util.List;/** * @ClassName: MyBaseMapper * @Description: * @Author: qjc * @Date: 2021/9/6 12:59 下午 */public interface MyBaseMapper<T> extends BaseMapper {List<T> mySelectList(@Param("ew") Wrapper<T> queryWrapper);}

最后一步将自定义的sql注入器注册到Spring容器中

@Beanpublic MySqlInjector mySqlInjector() {retu new MySqlInjector();}

然后进行测试

如何扩展MybatisPlus的BaseMapper(Sql注入器的使用、自动填充功能、逻辑删除功能) _ JavaClub全栈架构师技术笔记

 自动填充功能

我们创建的表中有创建用户,创建时间,删除标识字段,这些都是在创建用户时应该自动填充的,更新时间和更新用户字段是在更新用户信息的时候自动填充的

具体操作方法如下:在插入时需要自动填充的的字段上用注解@TableField(fill = FieldFill.INSERT),在更新时需要自动填充的字段上用注解@TableField(fill = FieldFill.UPDATE)

有其他需要填充的字段可参考FieldFill

如何扩展MybatisPlus的BaseMapper(Sql注入器的使用、自动填充功能、逻辑删除功能) _ JavaClub全栈架构师技术笔记

User实体如下

package com.qjc.entity;import com.baomidou.mybatisplus.annotation.*;import lombok.Data;import java.io.Serializable;import java.util.Date;@Data@TableName("mp_user")public class User implements Serializable {private static final long serialVersionUID = 1L;@TableIdprivate Long id;@TableField(fill = FieldFill.INSERT)private String createUser;@TableField(fill = FieldFill.INSERT)private Date createDate;@TableField(fill = FieldFill.UPDATE)private String updateUser;@TableField(fill = FieldFill.UPDATE)private Date updateDate;@TableField(fill = FieldFill.INSERT)private Integer deleteFlag;private String useame;private String password;private String birthday;}

然后定义MyMetaObjectHandler实现MetaObjectHandler接口,重写insertFill和updateFill方法

package com.qjc.handler;import com.baomidou.mybatisplus.core.handlers.MetaObjectHandler;import org.apache.ibatis.reflection.MetaObject;import org.springframework.stereotype.Component;import java.util.Date;/** * @ClassName: MyMetaObjectHandler * @Description: * @Author: qjc * @Date: 2021/9/6 4:01 下午 */@Componentpublic class MyMetaObjectHandler implements MetaObjectHandler {@Overridepublic void insertFill(MetaObject metaObject) {this.strictInsertFill(metaObject, "createUser", String.class, "qjc");this.strictInsertFill(metaObject, "createDate", Date.class, new Date());this.strictInsertFill(metaObject, "deleteFlag", Integer.class, 0);}@Overridepublic void updateFill(MetaObject metaObject) {this.strictUpdateFill(metaObject, "updateUser", String.class, "qjc");this.strictUpdateFill(metaObject, "updateDate", Date.class, new Date());}}

测试代码

@Testpublic void insert() {User user = new User();user.setUseame("lucy");user.setPassword("55555");user.setBirthday("2020-01-01");userMapper.insert(user);System.err.println(user.getId());}

结果如下

如何扩展MybatisPlus的BaseMapper(Sql注入器的使用、自动填充功能、逻辑删除功能) _ JavaClub全栈架构师技术笔记

 然后进行更新操作

@Testpublic void update() {User user = new User();user.setId(1435062640798867458L);user.setUseame("lucy");user.setPassword("66666");user.setBirthday("2020-01-01");userMapper.updateById(user);}

结果如下

如何扩展MybatisPlus的BaseMapper(Sql注入器的使用、自动填充功能、逻辑删除功能) _ JavaClub全栈架构师技术笔记

逻辑删除

我们在实际工作中,一般数据是不被删除的,要留存下来,所以会在每张表中添加删除标识来避免数据真的被删除

我们可以在删除标识deleteFlag字段上添加注解@TableLogic(value = "0", delval = "1")

然后测试删除,在删除之前我们先插入一条数据

@Testpublic void insert() {User user = new User();user.setUseame("cat");user.setPassword("777");user.setBirthday("2021-01-01");userMapper.insert(user);System.err.println(user.getId());}

结果如下

如何扩展MybatisPlus的BaseMapper(Sql注入器的使用、自动填充功能、逻辑删除功能) _ JavaClub全栈架构师技术笔记

然后使用BaseMapper提供的删除方法测试删除

@Testpublic void delete() {userMapper.deleteById(1435064337008955393L);}

结果如下

如何扩展MybatisPlus的BaseMapper(Sql注入器的使用、自动填充功能、逻辑删除功能) _ JavaClub全栈架构师技术笔记

我们发现在删除的时候更新人字段还是空的,这是因为逻辑删除并没有用到自动填充,所以我们自定义一个可以自动填充的删除方法

在MyBaseMapper中添加自动填充属性的删除方法

int myDeleteByIdWithFill(T t);

然后定义一个MyDeleteByIdWithFill方法类

package com.qjc.sqlInjector;import com.baomidou.mybatisplus.core.enums.SqlMethod;import com.baomidou.mybatisplus.core.injector.AbstractMethod;import com.baomidou.mybatisplus.core.metadata.TableFieldInfo;import com.baomidou.mybatisplus.core.metadata.TableInfo;import org.apache.ibatis.mapping.MappedStatement;import org.apache.ibatis.mapping.SqlSource;import java.util.List;import java.util.stream.Collectors;/** * @ClassName: MyDeleteById * @Description: 填充属性值的删除 * @Author: qjc * @Date: 2021/9/6 4:53 下午 */public class MyDeleteByIdWithFill extends AbstractMethod {@Overridepublic MappedStatement injectMappedStatement(Class<?> mapperClass, Class<?> modelClass, TableInfo tableInfo) {String sql;SqlMethod sqlMethod;if (tableInfo.isLogicDelete()) {// 进行逻辑删除List<TableFieldInfo> fieldInfos = getWithUpdateFillFields(tableInfo);// 删除时自动填充需要填充的属性值String sqlLogicSet = "SET " + fieldInfos.stream().map(i -> i.getSqlSet(null)).collect(Collectors.joining(EMPTY))+ tableInfo.getLogicDeleteSql(false, false);sql = String.format("<script>\nUPDATE %s %s WHERE %s=#{%s}\n</script>",tableInfo.getTableName(),sqlLogicSet,tableInfo.getKeyColumn(),tableInfo.getKeyProperty());SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, Object.class);retu addUpdateMappedStatement(mapperClass, modelClass, "myDeleteByIdWithFill", sqlSource);} else {sqlMethod = SqlMethod.DELETE_BY_ID;sql = String.format(sqlMethod.getSql(), tableInfo.getTableName(), tableInfo.getKeyColumn(),tableInfo.getKeyProperty());SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, Object.class);retu this.addDeleteMappedStatement(mapperClass, sqlMethod.getMethod(), sqlSource);}}/** * 过滤出更新时进行填充信息的字段列表 * * @param * @retu * @author qjc * @date 2021/9/6 5:09 下午 */private List<TableFieldInfo> getWithUpdateFillFields(TableInfo tableInfo) {retu tableInfo.getFieldList().stream().filter(TableFieldInfo::isWithUpdateFill).collect(Collectors.toList());}}

将该方法添加到MethodList中

public class MySqlInjector extends DefaultSqlInjector {@Overridepublic List<AbstractMethod> getMethodList(Class<?> mapperClass) {List<AbstractMethod> methodList = super.getMethodList(mapperClass);methodList.add(new MySelectList());methodList.add(new MyDeleteByIdWithFill());retu methodList;}}

然后再插入一条数据

@Testpublic void insert() {User user = new User();user.setUseame("dog");user.setPassword("888");user.setBirthday("2021-02-01");userMapper.insert(user);System.err.println(user.getId());}

结果如下

如何扩展MybatisPlus的BaseMapper(Sql注入器的使用、自动填充功能、逻辑删除功能) _ JavaClub全栈架构师技术笔记

测试自动填充属性的删除方法

@Testpublic void myDeleteByIdWithFill() {User user = new User();user.setId(1435066199628091394L);userMapper.myDeleteByIdWithFill(user);}

结果如下

如何扩展MybatisPlus的BaseMapper(Sql注入器的使用、自动填充功能、逻辑删除功能) _ JavaClub全栈架构师技术笔记

这时更新用户信息就填充进去了

demo地址:https://gitee.com/xiaorenwu_dashije/mybatis-plus-demo.git

作者:劈天造陆
来源链接:https://www.cnblogs.com/java-spring/p/15233953.html

版权声明:
1、JavaClub(https://www.javaclub.cn)以学习交流为目的,由作者投稿、网友推荐和小编整理收藏优秀的IT技术及相关内容,包括但不限于文字、图片、音频、视频、软件、程序等,其均来自互联网,本站不享有版权,版权归原作者所有。

2、本站提供的内容仅用于个人学习、研究或欣赏,以及其他非商业性或非盈利性用途,但同时应遵守著作权法及其他相关法律的规定,不得侵犯相关权利人及本网站的合法权利。
3、本网站内容原作者如不愿意在本网站刊登内容,请及时通知本站(javaclubcn@163.com),我们将第一时间核实后及时予以删除。





本文链接:https://www.javaclub.cn/java/112905.html

标签:MybatisPlus
分享给朋友:

“如何扩展MybatisPlus的BaseMapper(Sql注入器的使用、自动填充功能、逻辑删除功能)” 的相关文章

linux系统(CentOS7)下安装jdk8 2022年05月15日 21:54:24
SpringBoot整合hibeate纯注解版 2022年05月15日 21:58:07
windows下kafka搭建 2022年05月15日 21:58:15
专门为小白准备的入门级mybatis 2022年05月16日 19:53:11
SpringCloud简单实例 2022年05月16日 20:38:34
Java中四种访问修饰符的区别 2022年05月17日 16:04:05