In addition to Weibo, there is also WeChat
Please pay attention
WeChat public account
Shulou
2025-01-19 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >
Share
Shulou(Shulou.com)06/02 Report--
This article will explain in detail how Springboot implements a custom mybatis interceptor. The editor thinks it is very practical, so I share it with you as a reference. I hope you can get something after reading this article.
Preparation for practice:
Integrate mybatis, and then deliberately write three query methods, one is list list data, and two are single data.
Let's write an Interceptor that implements the mybatis framework in MybatisInterceptor:
MybatisInterceptor.java:
Import org.apache.ibatis.executor.Executor;import org.apache.ibatis.mapping.*;import org.apache.ibatis.plugin.*;import org.apache.ibatis.session.ResultHandler;import org.apache.ibatis.session.RowBounds;import org.springframework.stereotype.Component; import java.lang.reflect.Method;import java.util.* / * @ Author JCccc * @ Description * @ Date, 2021-12-14 16:56 * / @ Component@Intercepts ({@ Signature (type = Executor.class, method = "update", args = {MappedStatement.class, Object.class}), @ Signature (type = Executor.class, method = "query", args = {MappedStatement.class, Object.class, RowBounds.class ResultHandler.class}) public class MybatisInterceptor implements Interceptor {@ Override public Object intercept (Invocation invocation) throws Throwable {/ / get the execution parameter Object [] objects = invocation.getArgs () MappedStatement ms = (MappedStatement) objects [0]; / / parse the map method that executes sql, and start customizing the rule matching logic String mapperMethodAllName = ms.getId (); int lastIndex = mapperMethodAllName.lastIndexOf ("."); String mapperClassStr = mapperMethodAllName.substring (0, lastIndex); String mapperClassMethodStr = mapperMethodAllName.substring ((lastIndex + 1)); Class mapperClass = Class.forName (mapperClassStr) Method [] methods = mapperClass.getMethods (); Class returnType; for (Method method: methods) {if (method.getName (). Equals (mapperClassMethodStr)) {returnType = method.getReturnType (); if (returnType.isAssignableFrom (List.class)) {System.out.println ("return type is List") System.out.println ("do something on List");} else if (returnType.isAssignableFrom (Set.class)) {System.out.println ("return type is Set"); System.out.println ("do something on Set") } else {BoundSql boundSql = ms.getSqlSource () .getBoundSql (objects [1]); String oldSql = boundSql.getSql () .toLowerCase (Locale.CHINA) .replace ("[\ t\ n\ r]", ") If (! oldSql.contains ("LIMIT")) {String newSql = boundSql.getSql () .toLowerCase (Locale.CHINA) .replace ("[\ t\ n\ r]", ") +" LIMIT 1 " BoundSql newBoundSql = newBoundSql (ms.getConfiguration (), newSql, boundSql.getParameterMappings (), boundSql.getParameterObject ()); MappedStatement newMs = newMappedStatement (ms, new MyBoundSqlSqlSource (newBoundSql)); for (ParameterMapping mapping: boundSql.getParameterMappings ()) {String prop = mapping.getProperty () If (boundSql.hasAdditionalParameter (prop)) {newBoundSql.setAdditionalParameter (prop, boundSql.getAdditionalParameter (prop));}} Object [] queryArgs = invocation.getArgs (); queryArgs [0] = newMs System.out.println ("print new SQL statement" + newSql);} / / continue to execute logical return invocation.proceed () } @ Override public Object plugin (Object o) {/ / obtain proxy if (o instanceof Executor) {/ / if it is Executor (perform add, delete, change and search operation), block return Plugin.wrap (o, this);} else {return o Defines an internal helper class that wraps SQL * / class MyBoundSqlSqlSource implements SqlSource {private BoundSql boundSql; public MyBoundSqlSqlSource (BoundSql boundSql) {this.boundSql = boundSql;} @ Override public BoundSql getBoundSql (Object parameterObject) {return boundSql }} 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 ();} @ Override public void setProperties (Properties properties) {/ / read properties in mybatis configuration file}}
Simple code-side resolution:
① takes out the execution parameters, and there are a lot of things for us to use. I mainly use MappedStatement in this article. You can give full play to your ideas. If you hit debug, you can see the contents for yourself.
/ / get the execution parameter Object [] objects = invocation.getArgs (); MappedStatement ms = (MappedStatement) objects [0]
② here I mainly use the id taken from the MappedStatement to cut out which is the mapper of the currently executed sql, and then which is the method.
String mapperMethodAllName = ms.getId (); int lastIndex = mapperMethodAllName.lastIndexOf ("."); String mapperClassStr = mapperMethodAllName.substring (0, lastIndex); String mapperClassMethodStr = mapperMethodAllName.substring ((lastIndex + 1))
③ this is what I casually wrote, I directly based on the cut out of the mapper class to find out the method inside, mainly to come up with the return type of each method, because my practice is to determine a single pojo accepted mapper method, add a LIMIT 1, other LIST, SET, Page and so on, I will not expand for the time being.
Class mapperClass = Class.forName (mapperClassStr); Method [] methods = mapperClass.getMethods (); Class returnType
④ this code is the extension logic of this article, take out SqlSource from MappedStatement, then take out BoundSql, then add LIMIT 1 to a meal of operation, then new a new MappedStatement, and put an operation back into invocation.
BoundSql boundSql = ms.getSqlSource () .getBoundSql (objects [1]); String oldSql = boundSql.getSql () .toLowerCase (Locale.CHINA) .replace ("[\\ t\\ n\\ r]", ""); if (! oldSql.contains ("LIMIT")) {String newSql = boundSql.getSql (). ToLowerCase (Locale.CHINA) .replace ("[\ t\ n\ r]", ") +" LIMIT 1 " BoundSql newBoundSql = newBoundSql (ms.getConfiguration (), newSql, boundSql.getParameterMappings (), boundSql.getParameterObject ()); MappedStatement newMs = newMappedStatement (ms, new MyBoundSqlSqlSource (newBoundSql)); for (ParameterMapping mapping: boundSql.getParameterMappings ()) {String prop = mapping.getProperty (); if (boundSql.hasAdditionalParameter (prop)) {newBoundSql.setAdditionalParameter (prop, boundSql.getAdditionalParameter (prop)) }} Object [] queryArgs = invocation.getArgs (); queryArgs [0] = newMs; System.out.println ("print new SQL statement:" + newSql);}
OK, finally, simply try the effect:
Finally, I would like to reiterate that the content of this article is just a brick to attract jade, casually think of some practical effects, we can play according to our own ideas.
Finally, it is added to solve the problem of failure caused by the conflict between mybatis custom interceptor and pagehelper interceptor.
Solution:
Add an interceptor configuration class
MyDataSourceInterceptorConfig.java:
Import org.apache.ibatis.session.SqlSessionFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.context.ApplicationListener;import org.springframework.context.event.ContextRefreshedEvent;import org.springframework.stereotype.Component; import java.util.List; / * * @ Author JCccc * @ Description * @ Date 16:56 on 2021-12-14 * / @ Componentpublic class MyDataSourceInterceptorConfig implements ApplicationListener {@ Autowired private MybatisInterceptor mybatisInterceptor; @ Autowired private List sqlSessionFactories @ Override public void onApplicationEvent (ContextRefreshedEvent contextRefreshedEvent) {for (SqlSessionFactory factory: sqlSessionFactories) {factory.getConfiguration () .addInterceptor (mybatisInterceptor);}
Finally, add a little more.
The article aims at intercepting plug-ins for interfaces such as Executor.
In fact, you can also use ParameterHandler, ResultSetHandler, StatementHandler.
Whenever the methods of these four interface objects are executed, the intercept method will be entered, and then we can get different parameters according to different plug-ins.
Similar to:
Signature (method = "prepare", type = StatementHandler.class, args = {Connection.class,Integer.class})
Then you can make a conversion, or you can take out the relevant BoundSql and so on:
If (! (invocation.getTarget () instanceof RoutingStatementHandler)) {return invocation.proceed ();} RoutingStatementHandler statementHandler = (RoutingStatementHandler) invocation.getTarget (); BoundSql boundSql = statementHandler.getBoundSql (); String sql = boundSql.getSql (). ToUpperCase ()
ParameterHandler, ResultSetHandler, StatementHandler, Executor, different plug-ins intercept, there are different usage scenarios, if you want to go deep, you can take a deep look.
This is the end of this article on "how Springboot implements a custom mybatis interceptor". I hope the above content can be of some help to you, so that you can learn more knowledge. if you think the article is good, please share it for more people to see.
Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.
Views: 0
*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.
Continue with the installation of the previous hadoop.First, install zookooper1. Decompress zookoope
"Every 5-10 years, there's a rare product, a really special, very unusual product that's the most un
© 2024 shulou.com SLNews company. All rights reserved.