枚举类型用法_Mybatis-plus常见用法总结三

前面已经介绍了Mybatis-plus基本用法,今天为大家分享一些Mybatis-plus高级应用

  1. 逻辑删除
  2. 自动注入
  3. 枚举类型处理
  4. Sql注入器
  5. 多租户

表结构

CREATE TABLE `sys_role` (  `id` varchar(64) NOT NULL COMMENT '主键',  `code` varchar(64) NOT NULL DEFAULT '' COMMENT '角色编码',  `name` varchar(64) NOT NULL DEFAULT '' COMMENT '角色名',  `type` char(2) NOT NULL COMMENT '角色类型,1:管理员,2:普通',  `tenant_code` varchar(64) NOT NULL DEFAULT '' COMMENT '租户编码',  `create_user` varchar(64) NOT NULL DEFAULT '' COMMENT '创建用户',  `create_time` datetime NOT NULL COMMENT '创建时间',  `update_user` varchar(64) NOT NULL DEFAULT '' COMMENT '更新用户',  `update_time` datetime NOT NULL COMMENT '更新时间',  `is_del` char(1) NOT NULL DEFAULT '0' COMMENT '是否删除,0:未删除,1:删除',  PRIMARY KEY (`id`)) ENGINE=InnoDB DEFAULT CHARSET=utf8 COMMENT='角色';
4dc18fadcbec2857a83d82eb8df8b4de.png

逻辑删除

全局配置

在配置文件中增加如下配置

mybatis-plus:  global-config:    db-config:      logic-delete-field: isDel#全局逻辑删除字段值 3.3.0开始支持,详情看下面。      logic-delete-value: 1 # 逻辑已删除值(默认为 1)      logic-not-delete-value: 0 # 逻辑未删除值(默认为 0)

局部配置

在实体类删除字段上增加@TableLogic注解

/** 是否删除,0:未删除,1:删除 */@TableLogicprivate String isDel;

全局配置和局部配置实现的结果是一样的,下面针对局部配置做一下测试

@Autowiredprivate RoleMapper roleMapper;@Testpublic void logicDel() {    roleMapper.deleteById("1");}
a307bdf400178e435fd7319222a3bb17.png

从结果可以看出角色id为1数据的is_del被设置为1

使用Mybatis-plus自带方法删除、更新和查找都会where条件后面加上删除字段

以查询为例看一下效果

@Test void loginDel2() {    roleMapper.selectList(null);}
6f4ce5bd8cd70a883c257256eeba8117.png

从打印的sql中可以看出,在where后面添加了is_del='0'限定,所以要查询所有数据可以采用自定义sql实现

自动填充

在项目开发中,表中经常会定义一些公共的字段,例如:修改人,创建人。这时候我们可以采用 MyBatis-Plus 中

的字段自动填充功能去实现。

  1. 在实体类属性上增加@TableField(fill = FieldFill.INSERT_UPDATE)注解,如下所示
@Data@TableName("sys_role")public class Role {    /** 创建人 */    @TableField(fill = FieldFill.INSERT)    private String createUser;    /** 创建时间 */    @TableField(fill = FieldFill.INSERT)    private Date createTime;    /** 更新人 */    @TableField(fill = FieldFill.INSERT_UPDATE)    private String updateUser;    /** 更新时间 */    @TableField(fill = FieldFill.INSERT_UPDATE)    private Date updateTime;    /** 是否删除,0:未删除,1:删除 */    @TableLogic    private String isDel;}

TableField默认有四个

  • DEFAULT:默认不处理
  • INSERT:插入时填充字段
  • UPDATE:更新时填充字段
  • INSERT_UPDATE:插入和更新时填充字段
  1. 定义处理器
@Componentpublic class MyMetaObjectHandler implements MetaObjectHandler {​   public static String CREATEUSER_NAMEINBEAN = "createUser";    public static String CREATETIME_NAMEINBEAN = "createTime";    public static String UPDATEUSER_NAMEINBEAN = "updateUser";    public static String UPDATETIME_NAMEINBEAN = "updateTime";    @Override    public void insertFill(MetaObject metaObject) {        boolean createUser = metaObject.hasSetter(CREATEUSER_NAMEINBEAN);        if (createUser) {            this.strictInsertFill(metaObject, CREATEUSER_NAMEINBEAN, String.class, "admin");        }        boolean createTime = metaObject.hasSetter(CREATETIME_NAMEINBEAN);        if (createTime) {            this.strictInsertFill(metaObject, CREATETIME_NAMEINBEAN, LocalDateTime.class, LocalDateTime.now());        }        boolean updateUser = metaObject.hasSetter(UPDATEUSER_NAMEINBEAN);        if (updateUser) {            this.strictInsertFill(metaObject, UPDATEUSER_NAMEINBEAN, String.class, "admin");        }        boolean updateTime = metaObject.hasSetter(UPDATETIME_NAMEINBEAN);        if (updateTime) {            this.strictInsertFill(metaObject, UPDATETIME_NAMEINBEAN, LocalDateTime.class, LocalDateTime.now());        }    }​    @Override    public void updateFill(MetaObject metaObject) {        boolean updateUser = metaObject.hasSetter(UPDATEUSER_NAMEINBEAN);        if (updateUser) {            this.strictInsertFill(metaObject, UPDATEUSER_NAMEINBEAN, String.class, "amdin");        }        boolean updateTime = metaObject.hasSetter(UPDATETIME_NAMEINBEAN);        if (updateTime) {            this.strictInsertFill(metaObject, UPDATETIME_NAMEINBEAN, LocalDateTime.class, LocalDateTime.now());        }    }}​
  1. 测试
@Testvoid update() {    // 更新id为2角色的名字为测试2    Role role = new Role();    role.setName("测试2");    role.setId("2");    roleMapper.updateById(role);}
7e35c222404686dea8355b7b319eb3fa.png

在执行更新操作时自动加上更新人和更新时间

枚举类型处理器

自mybatis3.1.0开始,如果你无需使用原生枚举,可配置默认枚举来省略扫描通用枚举配置 默认枚举配置

  1. 定义枚举类,主要有两种方式

方法一:采用继承IEnum实现

@Getter@AllArgsConstructorpublic enum RoleType implements IEnum {    ADMIN("1"),    COMMON("2");    private String type;    @Override    public Serializable getValue() {        return type;    }}

方法二:注解方式,在枚举类需要解析的属性上增加@EnumValue注解

@Getter@AllArgsConstructorpublic enum RoleType {    ADMIN("1"),    COMMON("2"); @EnumValue//标记数据库存的值是type    private String type;}
  1. 定义实体类
@Data@TableName("sys_role")public class Role { /** 角色类型 */    private RoleType type;}
  1. 配置扫描的枚举包路径
mybatis-plus:  typeEnumsPackage: com.yanyu.spring.mybatisplus.enums
c66f01806047679d4f804758a35679da.png

从结果可以看出查询出的角色类型自动转换成了枚举ADMIN

Sql注入

当Mybatis-plus自带的原生方法不能满足我们的需求,我们可以利用sql注入器自定义sql

实现步骤:

  1. 创建自定义的类
public class DeleteByCodeMethod extends AbstractMethod {    @Override    public MappedStatement injectMappedStatement(Class> mapperClass, Class> modelClass, TableInfo tableInfo) {        // 执行的slq        String sql = "delete from "+ tableInfo.getTableName() +" where code = #{code}";        // Mapper接口方法名        String method = "deleteByCode";        SqlSource sqlSource = languageDriver.createSqlSource(configuration, sql, modelClass);        return addDeleteMappedStatement(mapperClass, method, sqlSource);    }}
  1. 创建注入器
@Componentpublic class MySqlInject extends DefaultSqlInjector {    @Override    public List getMethodList(Class> mapperClass) {        List methodList = super.getMethodList(mapperClass);        methodList.add(new DeleteByCodeMethod());        return methodList;    }}
  1. 在Mapper中加入自定义方法
public interface RoleMapper extends BaseMapper {    int deleteByCode(@Param("code") String code);}
  1. 测试
@Testvoid deleteByCode() {    // 删除编码为code的角色    roleMapper.deleteByCode("test");}
2b49cb1d205096eb3ba17445dcd0287f.png

从结果看,我们自定义的根据编码删除数据执行成功

Mybatis-plus官方为我们提供了三种自定义类

  • InsertBatchSomeColumn:批量新增数据,自选字段insert
  • AlwaysUpdateSomeColumnById:根据id更新固定字段
  • LogicDeleteByIdWithFill:根据id逻辑删除,并带字段填充功能

以InsertBatchSomeColumn为例,简单的演示一下怎么使用

  1. 在注入器中加入InsertBatchSomeColumn自定义类
@Componentpublic class MySqlInject extends DefaultSqlInjector {    @Override    public List getMethodList(Class> mapperClass) {        List methodList = super.getMethodList(mapperClass);        methodList.add(new DeleteByCodeMethod());        /**         * 不是逻辑删除的字段包括在内         */        methodList.add(new InsertBatchSomeColumn(t -> !t.isLogicDelete()));        return methodList;    }}
  1. 在Mapper中加入自定义方法
public interface RoleMapper extends BaseMapper {    int insertBatchSomeColumn(List list);}
  1. 测试
@Testvoid insertBatchSomeColumn() {    // 测试批量插入角色1和角色2    Role role1 = new Role();    role1.setCode("ROLE_1");    role1.setName("角色1");    role1.setType(RoleType.ADMIN);    Role role2 = new Role();    role2.setCode("ROLE_2");    role2.setName("角色2");    role2.setType(RoleType.ADMIN);    List roles = new ArrayList<>(Arrays.asList(role1,role2));    roleMapper.insertBatchSomeColumn(roles);}
6264a8f9a750365358fc48ff19c5c28a.png

多租户

租户实现

Mybatis-plus多租户依赖于分页插件,下面我们将简单介绍如何实现租户解析

  1. 定义租户解析器
@Beanpublic PaginationInterceptor paginationInterceptor() throws IOException {    PaginationInterceptor paginationInterceptor = new PaginationInterceptor();    TenantSqlParser tenantSqlParser = new TenantSqlParser();    tenantSqlParser.setTenantHandler(new TenantHandler() {        @Override        public Expression getTenantId(boolean select) {            return new StringValue("00000");        }        @Override        public String getTenantIdColumn() {            return "tenant_code";        }        @Override        public boolean doTableFilter(String tableName) {            /**             * 是否加租户信息,false->加,true->不加             */            return false;        }    });    paginationInterceptor.setSqlParserList(Arrays.asList(tenantSqlParser));    return paginationInterceptor;}
  1. 测试
@Testpublic void tenant() {    // 查询id为1的角色    roleMapper.selectById("1");}
fce7cb6c2d6e5ae4b1219c5ab53c1697.png

从结果看,sql执行时在查询条件中自动为我们加上了租户判断

特定sql过滤

在开发中有的方法不需要限定租户标识,实现方式有两种

  1. 方式一:通过在分页插件中自定义过滤器,具体实现如下所示
@Beanpublic PaginationInterceptor paginationInterceptor() throws IOException {    PaginationInterceptor paginationInterceptor = new PaginationInterceptor();    TenantSqlParser tenantSqlParser = new TenantSqlParser();    tenantSqlParser.setTenantHandler(new TenantHandler() {        @Override        public Expression getTenantId(boolean select) {            return new StringValue("00000");        }        @Override        public String getTenantIdColumn() {            return "tenant_code";        }        @Override        public boolean doTableFilter(String tableName) {            /**             * 是否加租户信息,false->加,true->不加             */            return false;        }    });    paginationInterceptor.setSqlParserList(Arrays.asList(tenantSqlParser));    paginationInterceptor.setSqlParserFilter(new ISqlParserFilter() {        /**         * true 不增加,false 增加         * @param metaObject         * @return         */        @Override        public boolean doFilter(MetaObject metaObject) {            MappedStatement ms = SqlParserHelper.getMappedStatement(metaObject);            if("具体方法".equals(ms.getId())) {                return true;            }            return false;        }    });    return paginationInterceptor;}
  1. 方式二:在不需要限定租户的方法上加入
public interface RoleMapper extends BaseMapper {    @SqlParser(filter = true)    int getByCode(String code);}

如果有哪里写得不对的,还请各位小友指正,只有不断试错,才能慢慢提高。如果你觉得对你有帮助,请点赞+关注,谢谢!!!!!!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/453050.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

NOIP 2011 Day2

tags: 贪心模拟NOIP categories:信息学竞赛总结计算系数 Solution 根据二项式定理,\[ \begin{align} (ab)^n\sum_{k0}^nC_{n}^{k}a^kb^{n-k} \end{align} \] 那么\[ \begin{align}(axby)^k&\sum_{p0}^kC_{k}^p(ax)^p(by)^{k-p}\\ &\sum_{p0}^k(C_{k}^pa^pb^{k-p})x^py^…

VS Code的golang开发配置 之 代码提示

之前用VS Code的时候&#xff0c;发现自己的代码的提示一直不好&#xff0c;换用JetBrain的Goland的代码提示是好了&#xff0c;但是比较占用资源。在网上找了一些资料&#xff0c;发现很多人也是遇到第三方或者自己的代码无法提示的情况&#xff0c;但是都没有下文了。后来发现…

使用oprofile分析性能瓶颈

使用oprofile分析性能瓶颈 1. 概述oprofile 是 Linux 平台上&#xff0c;类似 INTEL VTune 的一个功能强大的性能分析工具。其支持两种采样(sampling)方式&#xff1a;基于事件的采样(event based)和基于时间的采样(time based)。基于事件的采样是oprofile只记录特定事件&#…

什么是死锁

死锁是多个进程在运行过程中因竞争资源时产生的一种僵局。 各并发资源彼此等待对方拥有的资源&#xff0c;且在得到对方资源前不释放自己的资源。

python数据工程师 面试题_阿里P7工程师耗时两天整理的292道python大厂面试题,内含解析!...

前言相对于python大家应该都不会陌生吧&#xff01;现在java跟python可以算的是势均力敌了&#xff0c;所以现在学习python 的小伙伴也是越来越多了&#xff0c;可是学完之后就能找到称心如意的工作了吗&#xff1f;很多小伙伴学习Python的时候感觉很简单&#xff0c;但是到了去…

数组复制

在Java里面,可以用复制语句”AB”给基本类型的数据传递值,但是如果A,B是两个同类型的数组&#xff0c;复制就相当于将一个数组变量的引用传递给另一个数组&#xff1b;如果一个数组发生改变&#xff0c;那么引用同一数组的变量也要发生改变。 1.使用FOR循环,将数组的每个元素复…

IntelliJ IDEA 对于generated source的处理

IntelliJ IDEA 对于generated source的处理 学习了&#xff1a;https://stackoverflow.com/questions/5170620/unable-to-use-intellij-with-a-generated-sources-folder 如果有generated source &#xff0c;例如使用gRPC过程中生成的&#xff0c;可以使用鼠标右键点击使之成为…

产生死锁的原因

一 竞争资源&#xff0c;但是资源的数目不能满足进程的需要。 二 进程间推进顺序非法&#xff0c;进程在运行过程中请求和释放资源的顺序不当。

fabric shim安装合约_hyperledger fabric 开发第一个智能合约

一、编写智能合约代码HelloWorld.go&#xff0c;go语言实现&#xff0c;代码很简单&#xff0c;每个合约包含两个方法&#xff0c;Init、Invoke。package mainimport ("fmt""github.com/hyperledger/fabric/core/chaincode/shim""github.com/hyperled…

不能干一辈子开发???

程序员的职业生涯之我见 总是听到下面的论调 程序员干不了一辈子&#xff01; 程序员怎么也不能干一辈子吧&#xff01; 在中国程序员还能干一辈子&#xff1f; 过了&#xff08;30&#xff09;40我就干不动程序员了&#xff01; 每每听…

分布式缓存的25个优秀实践与线上案例 done

杨彪&#xff0c;蚂蚁金服技术专家&#xff0c;《分布式服务架构&#xff1a;原理、设计与实战》和《可伸缩服务架构&#xff1a;框架与中间件》作者。近10年互联网和游戏行业工作经验。本文节选自即将出版的《可伸缩服务架构&#xff1a;框架与中间件》一书&#xff0c;作者&a…

服务器性能估算参考(硬件-应用服务器)

2019独角兽企业重金招聘Python工程师标准>>> Environment(2013-05-24) two identical machines via a GB-Ethernet link a client machine generating HTTP requests with wrk as the load generator a server machine running the respective “benchmarkee”all …

产生死锁的四个必要条件

&#xff08;1&#xff09;互斥条件&#xff1a;进程对所分配到的资源不允许其他进程进行访问&#xff0c;若其他进程访问该资源&#xff0c;只能等待&#xff0c;直至占有该资源的进程使用完成后释放该资源 &#xff08;2&#xff09;请求和保持条件&#xff1a;进程获得一定的…

下拉选择_在管理Excel中实现联动下拉选择

在系统中常常出现这样的情况&#xff1a;由于下拉选择的数量太多了&#xff0c;难以高效选择。为此管理Excel通过通过引入多级联动选择的方式来减少下拉选择的困难度。先看下使用效果&#xff1a;联动下拉选择这个功能&#xff0c;在管理Excel中可以通过比较简单的配置方法实现…

图片预览

// 预览图片yulanFn: function (e) {var arr [];var that this;//获取当前图片的下表var indexw e.currentTarget.dataset.indexw;var index e.currentTarget.dataset.index;//数据源var pictures this.data.banner[indexw].shoppingCarouselList;var picture "http…

风雨20年:我所积累的20条编程经验

原文作者乔纳森丹尼可&#xff08;Jonathan Danylko&#xff09;是一位自由职业的web架构师和程序员&#xff0c;编程经验已超过20年&#xff0c;涉足领域有电子商务、生物技术、房地产、医疗、保险和公用事业。正如乔纳 森在文中所言&#xff0c;本文适合刚毕业的大学生和刚入…

JS跨域(ajax跨域、iframe跨域)解决方法及原理详解(jsonp)

这里说的js跨域是指通过js在不同的域之间进行数据传输或通信&#xff0c;比如用ajax向一个不同的域请求数据&#xff0c;或者通过js获取页面中不同域的框架中(iframe)的数据。只要协议、域名、端口有任何一个不同&#xff0c;都被当作是不同的域。 下表给出了相对 http://store…

xenserver 安装新硬盘_给Xenserver添加新硬盘

首先我们进入到xenserver的Console界面.然后按下enter进入命令模式,接下来.咱们先看看硬盘有没有存在输入fdisk -l出现如下提示:Disk /dev/sda: 500.1 GB, 500107862016 bytes255 heads, 63 sectors/track, 60801 cylindersUnits cylinders of 16065 * 512 8225280 bytesDevi…

go-study

package (包) 一个目录下面所有的.go文件的包名必须相同. 包名一般和目录名相同(是约定, 不是强制), 包名都小写main包是一个特殊的包名, 在main包中, 必须包含func main()函数导入包(import)的时候, 使用的是包所在目录的路径, 路径中不用包含包的名字, 在使用包的时候,直接用…