java:mybatis查询时自动添加tenantId和deleted查询条件

# 参考资料

https://blog.csdn.net/chenhz2284/article/details/139606486?spm=1001.2014.3001.5502

# 示例代码

【pom.xml】

<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
    <version>2.3.12.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-actuator</artifactId>
    <version>2.3.12.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.mybatis.spring.boot</groupId>
    <artifactId>mybatis-spring-boot-starter</artifactId>
    <version>2.2.0</version>
</dependency>
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-boot-starter</artifactId>
    <version>3.4.3.1</version>
</dependency>
<dependency>
    <groupId>com.baomidou</groupId>
    <artifactId>mybatis-plus-core</artifactId>
    <version>3.4.3.1</version>
</dependency>
<dependency>
    <groupId>com.alibaba.fastjson2</groupId>
    <artifactId>fastjson2</artifactId>
    <version>2.0.49</version>
</dependency>
<dependency>
    <groupId>com.mysql</groupId>
    <artifactId>mysql-connector-j</artifactId>
    <version>8.3.0</version>
</dependency>
<dependency>
    <groupId>ch.qos.logback</groupId>
    <artifactId>logback-classic</artifactId>
    <version>1.2.12</version>
</dependency>

【application.properties】

server.port=8080
spring.application.name=myMyBatisPlus

management.server.port=7001
management.endpoints.web.exposure.include=*

spring.datasource.driver-class-name=com.mysql.jdbc.Driver
spring.datasource.url=jdbc:mysql://192.168.44.228:3306/test
spring.datasource.username=root
spring.datasource.password=root

mybatis-plus.mapper-locations=classpath:mapper/*.xml

spring.shardingsphere.props.sql.show=true

【mapper/UserMapper.xml】

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.chz.myMyBatisPlus.persistence.mapper.UserMapper">

    <resultMap id="user" type="com.chz.myMyBatisPlus.persistence.po.User">
        <id column="id" property="id" />
        <result column="name" property="name" />
        <result column="sex" property="sex" />
        <result column="age" property="age" />
        <result column="email" property="email" />
        <result column="tenant_id" property="tenantId" />
        <result column="deleted" property="deleted" />
    </resultMap>

    <select id="selectUserById" parameterType="long" resultMap="user">
        SELECT * FROM chz_user
        WHERE id = #{id}
    </select>

</mapper>

【TestMybatisController.java】

package com.chz.myMyBatisPlus.controller;

@Slf4j
@RestController
@RequestMapping("/mybatis")
public class TestMybatisController {

    @Resource
    private UserMapper userMapper;

    @GetMapping("/selectAllUser")
    public List<User> selectAllUser() {
        LambdaQueryWrapper<User> queryWrapper = new LambdaQueryWrapper<>();
        List<User> users = userMapper.selectList(queryWrapper);
        return users;
    }
}

【MyBatisValidInterceptor.java】

package com.chz.myMyBatisPlus.interceptor;

@Intercepts({
        @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, 
                                                                    ResultHandler.class}),
})
@Component
@Slf4j
public class MyBatisValidInterceptor implements Interceptor {

    @Override
    public Object intercept(Invocation invocation) throws Throwable
    {
        Object[] args = invocation.getArgs();
        MappedStatement mappedStatement = (MappedStatement) args[0];
        String sqlKey = mappedStatement.getId();

        String sql = getSqlByInvocation(invocation);
        if (StringUtils.isBlank(sql)) {
            return invocation.proceed();
        }
        if (sqlKey.endsWith("Global")) {
            return invocation.proceed();
        }

        log.info("before ::: " + sql);
        sql = parseSql(sql);
        log.info("after ::: " + sql);

        resetSql2Invocation(invocation, sql);
        return invocation.proceed();
    }

    @Override
    public Object plugin(Object obj) {
        return Plugin.wrap(obj, this);
    }

    @Override
    public void setProperties(Properties arg0) {
    }

    public static String parseSql(String sql) throws JSQLParserException
    {
        Select stmt = (Select) CCJSqlParserUtil.parse(sql);

        PlainSelect plainSelect = (PlainSelect)stmt.getSelectBody();
        Expression whereExpression = plainSelect.getWhere();

        whereExpression = SqlParserUtils.andTenantIdExpression(whereExpression, 1L);
        whereExpression = SqlParserUtils.andDeletedExpression(whereExpression, false);

        plainSelect.setWhere(whereExpression);
        return plainSelect.toString();
    }

    private String getSqlByInvocation(Invocation invocation) {
        final Object[] args = invocation.getArgs();
        MappedStatement ms = (MappedStatement) args[0];
        Object parameterObject = args[1];
        BoundSql boundSql = ms.getBoundSql(parameterObject);
        return boundSql.getSql();
    }

    private void resetSql2Invocation(Invocation invocation, String sql) throws SQLException {
        final Object[] args = invocation.getArgs();
        MappedStatement statement = (MappedStatement) args[0];
        Object parameterObject = args[1];
        BoundSql boundSql = statement.getBoundSql(parameterObject);
        MappedStatement newStatement = newMappedStatement(statement, new BoundSqlSqlSource(boundSql));
        MetaObject msObject = MetaObject.forObject(newStatement, new DefaultObjectFactory(),
                new DefaultObjectWrapperFactory(), new DefaultReflectorFactory());
        msObject.setValue("sqlSource.boundSql.sql", sql);
        args[0] = newStatement;
    }

    private MappedStatement newMappedStatement(MappedStatement ms, SqlSource newSqlSource) {
        MappedStatement.Builder builder = new MappedStatement.Builder(ms.getConfiguration(), ms.getId(), newSqlSource,
                ms.getSqlCommandType());
        builder.resource(ms.getResource());
        builder.fetchSize(ms.getFetchSize());
        builder.statementType(ms.getStatementType());
        builder.keyGenerator(ms.getKeyGenerator());
        if (ms.getKeyProperties() != null && ms.getKeyProperties().length != 0) {
            StringBuilder keyProperties = new StringBuilder();
            for (String keyProperty : ms.getKeyProperties()) {
                keyProperties.append(keyProperty).append(",");
            }
            keyProperties.delete(keyProperties.length() - 1, keyProperties.length());
            builder.keyProperty(keyProperties.toString());
        }
        builder.timeout(ms.getTimeout());
        builder.parameterMap(ms.getParameterMap());
        builder.resultMaps(ms.getResultMaps());
        builder.resultSetType(ms.getResultSetType());
        builder.cache(ms.getCache());
        builder.flushCacheRequired(ms.isFlushCacheRequired());
        builder.useCache(ms.isUseCache());

        return builder.build();
    }

    class BoundSqlSqlSource implements SqlSource {

        private BoundSql boundSql;

        public BoundSqlSqlSource(BoundSql boundSql) {
            this.boundSql = boundSql;
        }

        @Override
        public BoundSql getBoundSql(Object parameterObject) {
            return boundSql;
        }
    }
}

【UserMapper.java】

package com.chz.myMyBatisPlus.persistence.mapper;

@Mapper
public interface UserMapper extends BaseMapper<User>
{
}

【User.java】

package com.chz.myMyBatisPlus.persistence.po;

@Data
@TableName(value = "chz_user")
public class User 
{
    private Long id;
    private String name;
    private String sex;
    private Integer age;
    private String email;
    private Long tenantId;
    private Boolean deleted;
}

【SqlParserUtils.java】

package com.chz.myMyBatisPlus.utils;

@Slf4j
public class SqlParserUtils
{
    public static BinaryExpression andTenantIdExpression(Expression where, Long tenantId)
    {
        EqualsTo equalsTo = new EqualsTo();
        equalsTo.setLeftExpression(new Column("tenant_id"));
        equalsTo.setRightExpression(new LongValue(tenantId));
        if (null != where) {
            if (where instanceof OrExpression) {
                return new AndExpression(equalsTo, new Parenthesis(where));
            } else {
                return new AndExpression(equalsTo, where);
            }
        }
        return equalsTo;
    }

    public static Expression andDeletedExpression(Expression where, Boolean deleted)
    {
        IsBooleanExpression isBooleanExpression = new IsBooleanExpression();
        isBooleanExpression.setLeftExpression(new Column("deleted"));
        isBooleanExpression.setIsTrue(deleted);
        if (null != where) {
            if (where instanceof OrExpression) {
                return new AndExpression(isBooleanExpression, new Parenthesis(where));
            } else {
                return new AndExpression(isBooleanExpression, where);
            }
        }
        return isBooleanExpression;
    }
}

【MyMyBatisPlusTest.java】

package com.chz.myMyBatisPlus;

@SpringBootApplication
public class MyMyBatisPlusTest {

    public static void main(String[] args)
    {
        SpringApplication.run(MyMyBatisPlusTest.class, args);
    }
}

启动【MyMyBatisPlusTest】,然后访问【http://localhost:8080/mybatis/selectAllUser】
在这里插入图片描述

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

纳税信用评级:企业的“金字招牌”

在快速发展的市场经济中&#xff0c;企业的信用状况越来越成为其竞争力的重要组成部分。而在税务领域&#xff0c;纳税信用评级更是衡量一个企业是否诚信经营的重要指标。今天&#xff0c;就让我们一起来深入了解纳税信用评级的相关知识。 一、纳税信用评级是什么&#xff1f;…

Python中的钩子函数(hooks)介绍使用

什么是hook&#xff1f; 钩子函数&#xff0c;顾名思义&#xff0c;就是把我们自己实现的自定义函数在某一时刻挂接到目标挂载点上去执行。 1. hook函数&#xff0c;就是我们自己实现的函数&#xff0c;函数类型与挂载点匹配&#xff08;返回值&#xff0c;参数列表&#xff0…

Fake news detection: A survey of graph neural network methods

abstract 各种社交网络的出现产生了大量的数据。捕获、区分和过滤真假新闻的有效方法变得越来越重要&#xff0c;特别是在 COVID-19 大流行爆发之后。本研究对假新闻检测系统的图神经网络 (GNN) 的现状和挑战进行了多方面、系统的回顾&#xff0c;并概述了使用 GNN 实现假新闻…

C++STL初阶(4):初识vector

vector是一个类模版&#xff0c;是一个顺序容器&#xff0c;底层思维就是顺序表&#xff0c;而顺序表的本质就是一个可以改变size的数组。本篇基于string的学习基础&#xff0c;我们对vector进行一个大致的了解和学习 1.基本介绍 1. vector 是表示可变大小数组的序列容器&#…

老生常谈!程序员为什么要阅读源代码?

大家好&#xff0c;我是码农先森。 阅读源码这是一个老生常谈的话题了&#xff0c;但又是很多人想做又没有付出行动的事情。前段时间我研究了 Swoole 的源代码&#xff0c;并且输出了系列的源码分析文章「感兴趣的朋友可以翻阅以前的文章」。虽然这个过程很枯燥和艰难&#xf…

css font-family

知乎的font-family的设置理解 -apple-system, BlinkMacSystemFont 这两个值是为了确保在macOS和iOS系统上能够使用系统默认字体进行文本渲染。-apple-system特别为Safari浏览器设计&#xff0c;而BlinkMacSystemFont则主要针对基于Chromium的浏览器&#xff08;如Chrome&#…

【Linux】shell——条件判断test,各种运算符,expr

条件判断——test 真——0 假——1 test expression or [ expression ] 整数运算符 字符串运算符 -z 长度是否为0 -n 长度是否不为0 str1 str2 str1 ! str2 补 &&-->逻辑与&#xff0c;前面为真后面才会执行 || -->逻辑或&#xff0c;前面为假后面才…

京东网页html+css简单制作1(附带源码和素材)

一.代码效果展示 代码html骨架结构分为头部top,颈部banner&#xff0c;中间部分main,腿部fortet-image,尾部fortter&#xff0c;五部分组成&#xff0c;从上至下&#xff0c;从左到右结构。&#xff08;总体因为没设计版心&#xff0c;所以位置比较乱&#xff09; 其中中部mai…

云动态摘要 2024-06-11

给您带来云厂商的最新动态,最新产品资讯和最新优惠更新。 最新优惠与活动 [低至1折]腾讯混元大模型产品特惠 腾讯云 2024-06-06 腾讯混元大模型产品特惠,新用户1折起! 云服务器ECS试用产品续用 阿里云 2024-04-14 云服务器ECS试用产品续用 最新产品更新 云服务器运维监…

设计模式-代理模式(结构型)

代理模式 代理模式是一种结构型模式&#xff0c;它可以通过一个类代理另一个类的功能。代理类持有被代理类的引用地址&#xff0c;负责将请求转发给代理类&#xff0c;并且可以在转发前后做一些处理 图解 角色 抽象主题&#xff08;Subject&#xff09;: 定义代理对象和被代理…

【安卓13 源码】Input子系统(2) - input系统与应用进程通信

点击手机屏幕&#xff0c;可以分发input 事件到对应的view&#xff0c;由上一节知道input 是运行在system 进程的&#xff0c;那应用进程与系统进程是如何通讯的呢&#xff0c;相信本文可以给到一点小小的答案。 先给个结论&#xff1a;应用在resume 的时候才去建立与input 服…

项目部署(前后端)

一&#xff1a;多环境概念&#xff1a; 借鉴来源&#xff1a;多环境设计_程序员鱼皮-多环境设计-CSDN博客 为什么需要多环境&#xff1a; 第一个例子&#xff1a;我们可以设想&#xff0c;我们肯定玩过王者荣耀&#xff0c;且王者荣耀也一直在不断更新&#xff0c;如果按我们…

cleanmymac清理时要一直输入密码 CleanMyMac X一直提示输入密码的解决方案

CleanMyMac X是一款专业的Mac清理软件&#xff0c;可智能清理mac磁盘垃圾和多余语言安装包&#xff0c;快速释放电脑内存&#xff0c;轻松管理和升级Mac上的应用。同时CleanMyMac X可以强力卸载恶意软件&#xff0c;修复系统漏洞&#xff0c;一键扫描和优化Mac系统。 在使用Cle…

【人工智能基础学习】Andrew Ng-机器学习基础笔记

⭐️我叫忆_恒心&#xff0c;一名喜欢书写博客的研究生&#x1f468;‍&#x1f393;。 如果觉得本文能帮到您&#xff0c;麻烦点个赞&#x1f44d;呗&#xff01; 近期会不断在专栏里进行更新讲解博客~~~ 有什么问题的小伙伴 欢迎留言提问欧&#xff0c;喜欢的小伙伴给个三连支…

HyperSnap软件最新版下载-HyperSnap官方最新版附加详细安装步骤

​HyperSnap是一个老牌优秀的屏幕截图工具&#xff0c;全新界面&#xff0c;不仅能抓取标准桌面程序&#xff0c;还能抓取 DirectX, 3Dfx Glide的 游戏视频或 DVD 屏幕图&#xff0c;能以 20 多种图形格式&#xff08;包括&#xff1a;BMP, GIF,JPEG, TIFF, PCX等&#xff09;保…

鸿蒙开发:应用组件跨设备交互(流转)【跨端迁移】

跨端迁移 概述 在用户使用设备的过程中&#xff0c;当使用情境发生变化时&#xff08;例如从室内走到户外或者周围有更适合的设备等&#xff09;&#xff0c;之前使用的设备可能已经不适合继续当前的任务&#xff0c;此时&#xff0c;用户可以选择新的设备来继续当前的任务&a…

C盘爆满?教你轻松清理无故产生的大量临时文件!

在电脑操作中&#xff0c;用户发现自己系统C盘爆满了&#xff0c;无缘无故产生了大量的临时文件&#xff0c;导致电脑运作变得卡顿&#xff0c;但不知道要怎么操作才能解决这个问题&#xff1f;接下来小编给小伙伴们带来不同的解决方法&#xff0c;轻松清理电脑上的临时文件。 …

【lesson7】服务端业务处理模块实现

文章目录 业务处理实现思路业务处理类设计成员变量成员函数RunModuleupLoadlistShowdownLoadgetETagInfo 业务处理实现思路 云备份项目中 &#xff0c;业务处理模块是针对客户端的业务请求进行处理&#xff0c;并最终给与响应。而整个过程中包含以下要实现的功能&#xff1a; …

这所大学25考研计算机学院专业课已全面改考为408!南京信息工程大学计算机考研!

南京信息工程大学&#xff08;Nanjing University of Information Science and Technology&#xff09;&#xff0c;简称“南信大”&#xff0c;位于江苏省南京市&#xff0c;是一所以大气科学为特色的全国重点大学&#xff0c;由江苏省人民政府、中华人民共和国教育部、中国气…

【lesson1】第三方库(jsoncpp,bundle, httplib)的介绍和使用

文章目录 jsoncpp库json 认识jsoncpp 认识jsoncpp 实现序列化jsoncpp 实现反序列化 bundle库bundle库实现文件压缩bundle库实现文件解压缩 httplib 库httplib 库搭建简单服务器httplib库搭建简单客户端 jsoncpp库 json 认识 json 是一种数据交换格式&#xff0c;采用完全独立…