MyBatis Interceptor拦截器高级用法
拦截插入操作
场景描述:插入当前数据时,同时复制当前数据插入多行。比如平台权限的用户,可以同时给其他国家级别用户直接插入数据
实现:
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.Interceptor;
import org.apache.ibatis.plugin.Intercepts;
import org.apache.ibatis.plugin.Invocation;
import org.apache.ibatis.plugin.Signature;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;import javax.annotation.Resource;
import java.lang.reflect.Constructor;
import java.util.List;
import java.util.Properties;/*** @author xxx* @version 1.0* @description 超级管理员创建基础资料,自动创建其他国家相应数据* @create 2024/3/2/002 13:48*/
@Slf4j
@Component
@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})
})
public class InsertionLinkageInterceptor implements Interceptor {@Value("${product.country-id.tables}")private String countryIdTables;@Resourceprivate UserService userService;@Overridepublic Object intercept(Invocation invocation) throws Throwable {// 只有超级管理员需要拦截if (!userService.isSuperAdmin()) {return invocation.proceed();}Object[] args = invocation.getArgs();MappedStatement ms = (MappedStatement) args[0];// 拦截插入操作if (ms.getSqlCommandType() == SqlCommandType.INSERT) {Object parameter = args[1];Class<?> aClass = parameter.getClass();TableName annotation = aClass.getAnnotation(TableName.class);String tableName = annotation.value();// 此处业务逻辑判断 此处做了一个表格名动态配置,可自行修改 //TODOif (!countryIdTables.contains(tableName)) {return invocation.proceed();}CountryBaseInfoDO parameterDO = (CountryBaseInfoDO) args[1];parameterDO.setCountryId(userService.getUserCountryId());parameterDO.setCode(IdUtils.generateCode());Constructor<?> constructor = aClass.getConstructor();CountryBaseInfoDO paramObject;List<Long> countryList = userService.getUserCountryIds();for (Long countryId : countryList) {paramObject = (CountryBaseInfoDO) constructor.newInstance();BeanUtils.copyProperties(parameterDO, paramObject);paramObject.setCountryId(countryId);Executor executor = (Executor) invocation.getTarget();executor.update(ms, paramObject);}}// 继续执行原始方法return invocation.proceed();}}
有些实体可能需要自行创建
拦截更新操作
更新数据时候,可能不止更新当前表,可能需要同时更新其他行数据
拦截查询
查询数据时候,可能需要同时默认加上某个条件
实现:
@Slf4j
@Component
@Intercepts({@Signature(type = StatementHandler.class, method = "prepare", args = {Connection.class, Integer.class})})
public class CommonQueryInterceptor implements Interceptor {private final static String FIELD_COUNTRY_ID = "country_id";@Value("${product.country-id.tables}")private String countryIdTables;@Resourceprivate UserService userService;@Overridepublic Object intercept(Invocation invocation) throws Throwable {// 超级管理员查看所有if (!userService.isSuperAdmin()) {return invocation.proceed();}RoutingStatementHandler handler = (RoutingStatementHandler) invocation.getTarget();//获取StatementHandler构造器StatementHandler delegate = (StatementHandler) ReflectUtil.getFieldValue(handler, "delegate");BoundSql boundSql = delegate.getBoundSql();String sql = boundSql.getSql();Statement statement = CCJSqlParserUtil.parse(sql);// 通过反射获取delegate父类BaseStatementHandler的mappedStatement属性MappedStatement mappedStatement = (MappedStatement) ReflectUtil.getFieldValue(delegate, "mappedStatement");SqlCommandType commandType = mappedStatement.getSqlCommandType();if (SqlCommandType.SELECT.equals(commandType)) {Select select = (Select) statement;PlainSelect selectBody = (PlainSelect) select.getSelectBody();Table fromItem = (Table) selectBody.getFromItem();String name = fromItem.getName();// 不在配置的表中,直接返回if (!countryIdTables.contains(name)) {return invocation.proceed();}appendCondition(selectBody);ReflectUtil.setFieldValue(boundSql, "sql", statement.toString());// 超级管理员插入时候同步插入所有国家的数据} else if (SqlCommandType.UPDATE.equals(commandType)) {String extraCondition = " or id in(" + userService.getNeedUpdateIds() + ")";sql = sql + extraCondition;ReflectUtil.setFieldValue(boundSql, "sql", sql);}return invocation.proceed();}/*** 追加条件*/private void appendCondition(PlainSelect selectBody) {try {// 获取where条件String stringExpression;try {EqualsTo where = (EqualsTo) selectBody.getWhere();stringExpression = where.getStringExpression();} catch (Exception e) {stringExpression = selectBody.getWhere().toString();}//如果字段搜索条件为空则搜索字段为空或指定数据StringBuilder sqlFilter = new StringBuilder(128);if (!stringExpression.contains(FIELD_COUNTRY_ID)) {sqlFilter.append("(country_id in ( ").append(userService.getNeedUpdateIds()).append(")) ");buildWhereClause(selectBody, sqlFilter.toString());}} catch (Exception e) {log.error("appendCondition error", e);//多表查询时由于不是最后一层,获取不到Table,继续获取子表
// SubSelect ss = (SubSelect) selectBody.getFromItem();
// PlainSelect subSelect = (PlainSelect) ss.getSelectBody();
// appendCondition(subSelect);}}private void buildWhereClause(PlainSelect select, String dataFilter) throws JSQLParserException {if (select.getWhere() == null) {select.setWhere(CCJSqlParserUtil.parseCondExpression(dataFilter));} else {AndExpression and = new AndExpression(CCJSqlParserUtil.parseCondExpression(dataFilter), select.getWhere());select.setWhere(and);}}}
相关文章:
MyBatis Interceptor拦截器高级用法
拦截插入操作 场景描述:插入当前数据时,同时复制当前数据插入多行。比如平台权限的用户,可以同时给其他国家级别用户直接插入数据 实现: import lombok.extern.slf4j.Slf4j; import org.apache.ibatis.executor.Executor; impor…...
Python学习入门(2)——进阶功能
14. 迭代器和迭代协议 在Python中,迭代器是支持迭代操作的对象,即它们可以一次返回其成员中的一个。任何实现了 __iter__() 和 __next__() 方法的对象都是迭代器。 class Count:def __init__(self, low, high):self.current lowself.high highdef __i…...
华为改进点
华为公司可以在员工福利方面做出改进,提高员工的工作满意度和忠诚度。例如,可以增加员工福利,如提供更多灵活的工作时间、提供更好的培训和发展机会、加大健康保障和福利待遇等。 此外,华为公司也可以加强与客户的沟通与合作&…...
分布式技术---------------消息队列中间件之 Kafka
目录 一、Kafka 概述 1.1为什么需要消息队列(MQ) 1.2使用消息队列的好处 1.2.1解耦 1.2.2可恢复性 1.2.3缓冲 1.2.4灵活性 & 峰值处理能力 1.2.5异步通信 1.3消息队列的两种模式 1.3.1点对点模式(一对一,消费者主动…...
BGP扩展知识总结
一、BGP的宣告问题 在BGP协议中每台运行BGP的设备上,宣告本地直连路由在BGP协议中运行BGP协议的设备,来宣告通过IGP学习到的未运行BGP协议设备产生的路由;(常见) 在BGP协议中宣告本地路由表中路由条目时,将…...
华为OD-C卷-按身高和体重排队[100分]
题目描述 某学校举行运动会,学生们按编号(1、2、3…n)进行标识,现需要按照身高由低到高排列,对身高相同的人,按体重由轻到重排列;对于身高体重都相同的人,维持原有的编号顺序关系。请输出排列后的学生编号…...
云原生(八)、Kubernetes基础(一)
K8S 基础 # 获取登录令牌 kubectl create token admin --namespace kubernetes-dashboard1、 NameSpace Kubernetes 启动时会创建四个初始名字空间 default:Kubernetes 包含这个名字空间,以便于你无需创建新的名字空间即可开始使用新集群。 kube-node-lease: 该…...
Linux 系统解压缩文件
Linux系统,可以使用unzip命令来解压zip文件 方法如下 1. 打开终端,在命令行中输入以下命令来安装unzip: sudo apt-get install unzip 1 2. 假设你想要将zip文件解压缩到名为"target_dir"的目录中,在终端中切换到目标路…...
linux如何使 CPU使用率保持在指定百分比?
目录 方法1:(固定在100%) 方法2:(可以指定0~100%) 方法3:使用ChaosBlade工具(0~100%) 方法1:(固定在100%) for i in seq 1 $(cat /pro…...
LLMs之Morphic:Morphic(一款具有生成式用户界面的人工智能答案引擎)的简介、安装、使用方法之详细攻略
LLMs之Morphic:Morphic(一款具有生成式用户界面的人工智能答案引擎)的简介、安装、使用方法之详细攻略 目录 Morphic的简介 1、技术栈 Morphic的安装和使用方法 1、克隆仓库 2、安装依赖 3、填写密钥 4、本地运行应用 部署 Morphic的简介 2024年4月初发布ÿ…...
[react] useState的一些小细节
1.无限循环 因为setState修改是异步的,加上会触发函数重新渲染, 如果代码长这样 一秒再修改,然后重新触发setTImeout, 然后再触发,重复触发循环 如果这样呢 还是会,因为你执行又会重新渲染 2.异步修改数据 为什么修改多次还是跟不上呢? 函数传参解决 因为是异步修改 ,所以…...
蓝桥杯【第15届省赛】Python B组
这题目难度对比历届是相当炸裂的简单了…… A:穿越时空之门 【问题描述】 随着 2024 年的钟声回荡,传说中的时空之门再次敞开。这扇门是一条神秘的通道,它连接着二进制和四进制两个不同的数码领域,等待着勇者们的探索。 在二进制…...
CSS aspect-ratio属性设置元素宽高比
aspect-ratio 是CSS的一个属性,用于设置元素的期望宽高比。它设置确保元素保持特定的比例,不受其内容或容器大小的影响。 语法: aspect-ratio: <ratio>;其中 <ratio> 是一个由斜杠(/)分隔的两个数字&…...
Jones矩阵符号运算
文章目录 Jones向量Jones矩阵 有关Jones矩阵、Jones向量的基本原理,可参考这个: 通过Python理解Jones矩阵,本文主要介绍sympy中提供的有关偏振光学的符号计算工具 Jones向量 Jones向量是描述光线偏振状态的重要工具,例如一个偏振…...
解决 App 自动化测试的常见痛点!
App 自动化测试中有些常见痛点问题,如果框架不能很好的处理,就可能出现元素定位超时找不到的情况,自动化也就被打断终止了。很容易打消做自动化的热情,导致从入门到放弃。比如下面的两个问题: 一是 App 启动加载时间较…...
2016NOIP普及组真题 1. 买铅笔
线上OJ: 一本通:http://ybt.ssoier.cn:8088/problem_show.php?pid1973 核心思想: 向上取整的代码 (m (n-1))/n 。(本题考点与2023年J组的第一和第二题一样) 比如需要买31支笔,每包30支,则需要…...
机器学习—数据集(二)
1可用数据集 公司内部 eg:百度 数据接口 花钱 数据集 学习阶段可用的数据集: sklearn:数据量小,方便学习kaggle:80万科学数据,真实数据,数据量大UCI:收录了360个数据集,覆盖科学、生活、经济等…...
华为S5735S核心交换配置实例
以下脚本实现创建vlan2,3,IP划分,DHCP启用,接口划分,ssh,telnet,http,远程登录启用 默认用户创建admin/admin123提示首次登录需要更改用户密码S5735产品手册更多功能配置,移步官网参考手册配置 system-viewsysname t…...
Mysql主从复制安装配置
mysql主从复制安装配置 1、基础设置准备 #操作系统: centos6.5 #mysql版本: 5.7 #两台虚拟机: node1:192.168.85.111(主) node2:192.168.85.112(从)2、安装mysql数据库 #详细安装和卸载的步骤…...
【刷题】图论——最小生成树:Prim、Kruskal【模板】
假设有n个点m条边。 Prim适用于邻接矩阵存的稠密图,时间复杂度是 O ( n 2 ) O(n^2) O(n2),可用堆优化成 O ( n l o g n ) O(nlogn) O(nlogn)。 Kruskal适用于稀疏图,n个点m条边,时间复杂度是 m l o g ( m ) mlog(m) mlog(m)。 Pr…...
使用uniapp实现小程序获取wifi并连接
Wi-Fi功能模块 App平台由 uni ext api 实现,需下载插件:uni-WiFi 链接:https://ext.dcloud.net.cn/plugin?id10337 uni ext api 需 HBuilderX 3.6.8 iOS平台获取Wi-Fi信息需要开启“Access WiFi information”能力登录苹果开发者网站&…...
回忆杀之手搓当年搓过的Transformer
整体代码 import mathimport paddle import paddle.nn as nn import paddle.nn.functional as Fclass MaskMultiHeadAttention(nn.Layer):def __init__(self, hidden_size, num_heads):super(MaskMultiHeadAttention, self).__init__()assert hidden_size % num_heads 0, &qu…...
【AR】使用深度API实现虚实遮挡
遮挡效果 本段描述摘自 https://developers.google.cn/ar/develop/depth 遮挡是深度API的应用之一。 遮挡(即准确渲染虚拟物体在现实物体后面)对于沉浸式 AR 体验至关重要。 参考下图,假设场景中有一个Andy,用户可能需要放置在包含…...
python-pytorch实现skip-gram 0.5.001
python-pytorch实现skip-gram 0.5.000 数据加载、切词准备训练数据准备模型和参数训练保存模型加载模型简单预测获取词向量画一个词向量的分布图使用词向量计算相似度参考数据加载、切词 按照链接https://blog.csdn.net/m0_60688978/article/details/137538274操作后,可以获得…...
C语言:约瑟夫环问题详解
前言 哈喽,宝子们!本期为大家带来一道C语言循环链表的经典算法题(约瑟夫环)。 目录 1.什么是约瑟夫环2.解决方案思路3.创建链表头结点4.创建循环链表5.删除链表6.完整代码实现 1.什么是约瑟夫环 据说著名历史学家Josephus有过以下…...
【刷题篇】回溯算法(二)
文章目录 1、求根节点到叶节点数字之和2、二叉树剪枝3、验证二叉搜索树4、二叉搜索树中第K小的元素5、二叉树的所有路径 1、求根节点到叶节点数字之和 给你一个二叉树的根节点 root ,树中每个节点都存放有一个 0 到 9 之间的数字。 每条从根节点到叶节点的路径都代表…...
Windows系统本地部署Jupyter Notebook并实现公网访问编辑笔记
文章目录 1.前言2.Jupyter Notebook的安装2.1 Jupyter Notebook下载安装2.2 Jupyter Notebook的配置2.3 Cpolar下载安装 3.Cpolar端口设置3.1 Cpolar云端设置3.2.Cpolar本地设置 4.公网访问测试5.结语 1.前言 在数据分析工作中,使用最多的无疑就是各种函数、图表、…...
自动化运维(二十七)Ansible 实战Shell 插件和模块工具
Ansible 支持多种类型的插件,这些插件可以帮助你扩展和定制 Ansible 的功能。每种插件类型都有其特定的用途和应用场景。今天我们一起学习Shell 插件和模块工具。 一、 Shell 插件 Ansible shell 插件决定了 Ansible 如何在远程系统上执行命令。这些插件非常关键&a…...
Jenkins使用-绑定域控与用户授权
一、Jenkins安装完成后,企业中使用,首先需要绑定域控以方便管理。 操作方法: 1、备份配置文件,防止域控绑定错误或授权策略选择不对,造成没办法登录,或登录后没有权限操作。 [roottest jenkins]# mkdir ba…...
【前端】es-drager 图片同比缩放 缩放比 只修改宽 只修改高
【前端】es-drager 图片同比缩放 缩放比 ES Drager 拖拽组件 (vangleer.github.io) 核心代码 //初始宽 let width ref(108)//初始高 let height ref(72)//以下两个变量 用来区分是单独的修改宽 还是高 或者是同比 //缩放开始时的宽 let oldWidth 0 //缩放开始时的高 let o…...
深一网站建设/十大免费无代码开发软件
早晨起床时间:12:30 晚上休息时间:0:28 今日总结:休息中。...
网站不用备案/搜狗推广
ACL访问控制列表及配置ACL(访问控制列表)ACL作用ACL工作原理ACL种类ACL应用原则ACL应用规则配置任务1任务2任务3ACL(访问控制列表) 读取第三层、第四层包头 信息根据预先定义好的规则对包进行过滤 访问控制列表在接口应用的方向 出:已经过路由器的处理,正离开路由…...
wordpress模版c2c商城/网站推广有哪些方式
众所周知,系统的更新是为了增强系统的稳定性,优化流畅性,有的则是优化了续航,修复BUG,优化安全性等等。对于国内很多定制UI,新手机更新的频率以及Android的版本都能保持一段时间的稳定。新系统一般会针对目…...
支付网站怎么做/网上有卖网站链接的吗
0.引子 读取应用程序配置文件(比如***.exe.config)的方法有很多, .NET自带的ConfigurationManager也很方便. 这篇文章主要探讨类库生成的dll文件的配置信息的读取——特别地, 用户自定义SectionGroupName和SectionName(这里是指不同于appSettings的形式), 这种方式配置信息的…...
做网站的技术支持/网站排名优化软件哪家好
什么是RDD:RDD叫做分布式数据集,是Spark最基本的数据抽象,代码中是一个抽象类,它代表的是一个不可变、可分区、里面的元素可并行计算的集合。RDD里面封装的是计算逻辑。RDD的属性:1. 一个分区(Partition),即数据集的基…...
seo网站设计费用/免费建立自己的网站
前言:之前工作中做过两个功能,就是之前写的这两篇博客,最近几天有个想法,给它做成一个springboot的start启动器,直接引入依赖,写好配置就能用了 springboot使用自定义注解实现接口参数解密,普通…...