Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

What is the function of binding module in MyBatis

2025-01-15 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Internet Technology >

Share

Shulou(Shulou.com)06/02 Report--

What is the role of the binding module in MyBatis, many novices are not very clear about this, in order to help you solve this problem, the following editor will explain in detail for you, people with this need can come to learn, I hope you can gain something.

The MyBatis binding module analyzes the package where the binding function code resides

Org.apache.ibatis.binding

The function of binding module

Encapsulating ibatis programming model in ibatis programming model, SqlSession is the entry of sql execution, and the practical method is in the form of sqlSession.selectOne (namespace+id, parameter list) (example: sqlSession.selectOne ("com.enjoylearning.mybatis.mapper.TUserMapper.selectByPrimaryKey", 2)), which is not easy to maintain and read.

Problems that need to be solved

Find the corresponding method in SqlSession (insert | update | select)

Find the namespace and method name (2D coordinates)

Transfer parameters

Core class

The registry of the MapperRegistry:mapper interface and the corresponding proxy factory; is a member variable of Configuration

MapperProxyFactory: an instance object used to generate a dynamic proxy for the mapper interface; make sure that the mapper instance object is a local variable (why not cache it? See the end of the article)

MapperMethod: encapsulates the corresponding method information in the Mapper interface to follow the information of the corresponding sql statement. The MapperMethod object does not record any state, so it can be shared among multiple proxy objects; sqlCommand: encapsulates sql statements; MtehodSignature: encapsulates the input parameters and return types of the mapper interface

Personal understanding

MapperRegistry's Map > knownMappers = new HashMap (); key:mapper 's Class object value: the factory that produces examples of dynamic agents for this mapper

MapperProxyFactory:Map methodCache key: information of the method's reflection class value method (sql statement, input parameter, return value)

The related code public class MapperRegistry {private final Configuration config;//config object, mybatis globally unique / / records the relationship between the mapper interface and the corresponding MapperProxyFactory private final Map > knownMappers = new HashMap (); public MapperRegistry (Configuration config) {this.config = config;} @ SuppressWarnings ("unchecked") public T getMapper (Class type, SqlSession sqlSession) {final MapperProxyFactory mapperProxyFactory = (MapperProxyFactory) knownMappers.get (type) If (mapperProxyFactory = = null) {throw new BindingException ("Type" + type + "is not known to the MapperRegistry.");} try {return mapperProxyFactory.newInstance (sqlSession);} catch (Exception e) {throw new BindingException ("Error getting mapper instance. Cause: "+ e, e);} / * is used to generate instance objects for dynamic proxies for mapper interfaces The class object private final Class mapperInterface;//key of the * @ author Lasse Voss * / public class MapperProxyFactory {/ / mapper interface is the method object of a method in the mapper interface, and value is the corresponding MapperMethod,MapperMethod object that does not record any status information, so it can share private final Map methodCache = new ConcurrentHashMap () among multiple proxy objects; public class MapperMethod {/ / gets the namespace of the method from configuration. The name of the method and the type of the SQL statement private final SqlCommand command; / / encapsulates the information about the mapper interface method (input parameter, return type); procedure of private final MethodSignature method;getMapper

The class object private final Class mapperInterface;//key of the public class MapperProxyFactory {/ / mapper interface is the method object of a method in the mapper interface, and value is the corresponding MapperMethod,MapperMethod object that does not record any state information, so it can share private final Map methodCache = new ConcurrentHashMap () among multiple proxy objects; public MapperProxyFactory (Class mapperInterface) {this.mapperInterface = mapperInterface;} public Class getMapperInterface () {return mapperInterface;} public Map getMethodCache () {return methodCache } @ SuppressWarnings ("unchecked") protected T newInstance (MapperProxy mapperProxy) {/ / create a dynamic proxy object return (T) Proxy.newProxyInstance (mapperInterface.getClassLoader (), new Class [] {mapperInterface}, mapperProxy) that implements the mapper interface;} public T newInstance (SqlSession sqlSession) {/ / each call creates a new MapperProxy object final MapperProxy mapperProxy = new MapperProxy (sqlSession, mapperInterface, methodCache); return newInstance (mapperProxy);}}

Two newInstance methods generate the dynamic proxy object MapperProxy of mapper

Public class MapperProxy implements InvocationHandler, Serializable {. @ Override public Object invoke (Object proxy, Method method, Object [] args) throws Throwable {try {if (Object.class.equals (method.getDeclaringClass () {/ / if Object's own method does not enhance return method.invoke (this, args);} else if (isDefaultMethod (method)) {return invokeDefaultMethod (proxy, method, args) }} catch (Throwable t) {throw ExceptionUtil.unwrapThrowable (t);} / / get the mapperMethod object from the cache. If it is not in the cache, create one and add it to the cache final MapperMethod mapperMethod = cachedMapperMethod (method); / / call the execute method to execute sql return mapperMethod.execute (sqlSession, args) } private MapperMethod cachedMapperMethod (Method method) {return methodCache.computeIfAbsent (method, k-> new MapperMethod (mapperInterface, method, sqlSession.getConfiguration ());}

From the invoke method, we can see that mapperMethod called the execute method.

Public class MapperMethod {. Public Object execute (SqlSession sqlSession, Object [] args) {Object result; / / call different switch (command.getType ()) {case INSERT: {Object param = method.convertArgsToSqlCommandParam (args); result = rowCountResult (sqlSession.insert (command.getName (), param)) depending on the type of switch statement and the parameters returned by the API; break } case UPDATE: {Object param = method.convertArgsToSqlCommandParam (args); result = rowCountResult (sqlSession.update (command.getName (), param)); break;} case DELETE: {Object param = method.convertArgsToSqlCommandParam (args); result = rowCountResult (sqlSession.delete (command.getName (), param)); break } case SELECT: if (method.returnsVoid () & & method.hasResultHandler ()) {/ / return value is void executeWithResultHandler (sqlSession, args); result = null;} else if (method.returnsMany ()) {/ / return value is collection or array result = executeForMany (sqlSession, args) } else if (method.returnsMap ()) {/ / return value is map result = executeForMap (sqlSession, args);} else if (method.returnsCursor ()) {/ / return value is cursor result = executeForCursor (sqlSession, args);} else {/ / processes the case that it is returned as a single object / / parses the parameter Object param = method.convertArgsToSqlCommandParam (args) through the parameter parser Result = sqlSession.selectOne (command.getName (), param); if (method.returnsOptional () & (result = = null | |! method.getReturnType (). Equals (result.getClass () {result = OptionalUtil.ofNullable (result);}} break; case FLUSH: result = sqlSession.flushStatements (); break Default: throw new BindingException ("Unknown execution method for:" + command.getName ());} if (result = = null & & method.getReturnType (). IsPrimitive () &! method.returnsVoid ()) {throw new BindingException ("Mapper method'" + command.getName () + "attempted to return null from a method with a primitive return type (" + method.getReturnType () + ");} return result;}

Focus on result = sqlSession.selectOne (command.getName (), param); the usage of ibatis is used here

Question and answer

MapperProxy still relies on sqlSession for query. According to the current code structure, if mapperProxy is cached, when sqlSession fails, mapperProxy also fails. If you modify the generation structure, then sqlSession will be used as a query parameter

/ / the original TUser user = mapper.selectByPrimaryKey (2); / / the revised method TUser user = mapper.selectByPrimaryKey (sqslSession,2). Is it helpful for you to read the above content? If you want to know more about the relevant knowledge or read more related articles, please follow the industry information channel, thank you for your support.

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.

Share To

Internet Technology

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report