如何实现MyBatis自定义SQL拦截器
发表于:2025-01-20 作者:千家信息网编辑
千家信息网最后更新 2025年01月20日,本篇内容主要讲解"如何实现MyBatis自定义SQL拦截器",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"如何实现MyBatis自定义SQL拦截器"吧!定义
千家信息网最后更新 2025年01月20日如何实现MyBatis自定义SQL拦截器定义是否开启注解
注册SQL 拦截器
处理逻辑
如何使用
本篇内容主要讲解"如何实现MyBatis自定义SQL拦截器",感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习"如何实现MyBatis自定义SQL拦截器"吧!
定义是否开启注解
定义是否开启注解, 主要做的一件事情就是是否添加 SQL 拦截器。
// 全局开启@Retention(RetentionPolicy.RUNTIME)@Target(ElementType.TYPE)@Documented@Import(MyBatisSqlInterceptorConfiguration.class)public @interface EnableSqlInterceptor {}// 自定义注解@Target({ElementType.METHOD })@Retention(RetentionPolicy.RUNTIME)public @interface DataScope {}
注册SQL 拦截器
注册一个 SQL 拦截器,会对符合条件的 SQL 查询操作进行拦截。
public class MyBatisSqlInterceptorConfiguration implements ApplicationContextAware { @Override public void setApplicationContext(ApplicationContext applicationContext) throws BeansException { SqlSessionFactory sqlSessionFactory = applicationContext.getBean(SqlSessionFactory.class); sqlSessionFactory.getConfiguration().addInterceptor(new MyBatisInterceptor()); }}
处理逻辑
在处理逻辑中,我主要是做一个简单的 limit 1 案例,如果是自己需要做其他的逻辑需要修改
@Slf4j@Intercepts( { @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class}), @Signature(type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class, ResultHandler.class, CacheKey.class, BoundSql.class}), })public class MyBatisInterceptor implements Interceptor { private static final Logger LOGGER = LoggerFactory.getLogger(MyBatisInterceptor.class); @Override public Object intercept(Invocation invocation) throws Throwable { // TODO Auto-generated method stub Object[] args = invocation.getArgs(); MappedStatement ms = (MappedStatement) args[0]; Object parameter = args[1]; RowBounds rowBounds = (RowBounds) args[2]; ResultHandler resultHandler = (ResultHandler) args[3]; Executor executor = (Executor) invocation.getTarget(); CacheKey cacheKey; BoundSql boundSql; //由于逻辑关系,只会进入一次 if (args.length == 4) { //4 个参数时 boundSql = ms.getBoundSql(parameter); cacheKey = executor.createCacheKey(ms, parameter, rowBounds, boundSql); } else { //6 个参数时 cacheKey = (CacheKey) args[4]; boundSql = (BoundSql) args[5]; } DataScope dataScope = getDataScope(ms); if (Objects.nonNull(dataScope)) { String origSql = boundSql.getSql(); log.info("origSql : {}", origSql); // 组装新的 sql // todo you weaving business String newSql = origSql + " limit 1"; // 重新new一个查询语句对象 BoundSql newBoundSql = new BoundSql(ms.getConfiguration(), newSql, boundSql.getParameterMappings(), boundSql.getParameterObject()); // 把新的查询放到statement里 MappedStatement newMs = newMappedStatement(ms, new BoundSqlSource(newBoundSql)); for (ParameterMapping mapping : boundSql.getParameterMappings()) { String prop = mapping.getProperty(); if (boundSql.hasAdditionalParameter(prop)) { newBoundSql.setAdditionalParameter(prop, boundSql.getAdditionalParameter(prop)); } } args[0] = newMs; if (args.length == 6) { args[5] = newMs.getBoundSql(parameter); } } LOGGER.info("mybatis intercept sql:{},Mapper方法是:{}", boundSql.getSql(), ms.getId()); return invocation.proceed(); } 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) { builder.keyProperty(ms.getKeyProperties()[0]); } 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(); } private DataScope getDataScope(MappedStatement mappedStatement) { String id = mappedStatement.getId(); // 获取 Class Method String clazzName = id.substring(0, id.lastIndexOf('.')); String mapperMethod = id.substring(id.lastIndexOf('.') + 1); Class> clazz; try { clazz = Class.forName(clazzName); } catch (ClassNotFoundException e) { return null; } Method[] methods = clazz.getMethods(); DataScope dataScope = null; for (Method method : methods) { if (method.getName().equals(mapperMethod)) { dataScope = method.getAnnotation(DataScope.class); break; } } return dataScope; } @Override public Object plugin(Object target) { // TODO Auto-generated method stub LOGGER.info("MysqlInterCeptor plugin>>>>>>>{}", target); return Plugin.wrap(target, this); } @Override public void setProperties(Properties properties) { // TODO Auto-generated method stub String dialect = properties.getProperty("dialect"); LOGGER.info("mybatis intercept dialect:>>>>>>>{}", dialect); } /** * 定义一个内部辅助类,作用是包装 SQL */ class BoundSqlSource implements SqlSource { private BoundSql boundSql; public BoundSqlSource(BoundSql boundSql) { this.boundSql = boundSql; } public BoundSql getBoundSql(Object parameterObject) { return boundSql; } }}
如何使用
我们在 XXXMapper 中对应的数据操作方法只要加入 @DataScope 注解即可。
@Mapperpublic interface OrderMapper { @Select("select 1 ") @DataScope Intger selectOne();}
到此,相信大家对"如何实现MyBatis自定义SQL拦截器"有了更深的了解,不妨来实际操作一番吧!这里是网站,更多相关内容可以进入相关频道进行查询,关注我们,继续学习!
拦截器
注解
逻辑
查询
方法
内容
参数
处理
学习
实用
更深
事情
作用
全局
兴趣
实用性
实际
对象
就是
操作简单
数据库的安全要保护哪些东西
数据库安全各自的含义是什么
生产安全数据库录入
数据库的安全性及管理
数据库安全策略包含哪些
海淀数据库安全审计系统
建立农村房屋安全信息数据库
易用的数据库客户端支持安全管理
连接数据库失败ssl安全错误
数据库的锁怎样保障安全
串口服务器和交换机
网络安全外部威胁是指什么
914网络安全
数据库管理的体系架构
数据库中传递函数依赖的定义
拉萨网络安全保障
水稻种子数据库
软件开发技术合同享受免税政策吗
网络安全知识的画怎么画
科研数据库技术文案
数据库怎么加字段含义
手机软件开发是什么意思
酒店网络安全宣传语
达梦数据库查询授权日期
软件开发安全方法
软件开发的开会主题
软件开发行业税务规定
宝游网络技术有限公司
安徽pdu服务器电源出售
Mts 软件开发
延庆区正规软件开发要求
怎么查询邮件服务器
网络安全三个结构ISAP
乌鲁木齐网络安全培训费用多少
全国网络安全课送进龙游校园
杭州乒乓球软件开发
以网络安全为主题画板
数据库的er图线
国家经济领域内网络安全问题
银行软件开发公积金