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/01 Report--
This article will explain in detail how to use @ MapKey in MyBatis. 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.
The magic background of MyBatis @ MapKey
In actual development, there are some scenarios that require us to return a collection of Map whose primary key is Key or unique key is Key and Entity is Value, such as Map, and then we can get the Entity directly through map.get (key).
Realize
MyBatis provides us with this implementation, and the Dao example is as follows:
Public interface UserDao {@ MapKey ("id") Map selectByIdList (@ Param ("idList") List idList);}
It is important to note that if the select return type in Mapper.xml is an element of List, in the above example, resultType is User, because the selectMap query is selectList first, followed by processing List.
Source code analysis package org.apache.ibatis.session.defaults;public class DefaultSqlSession implements SqlSession {. Public Map selectMap (String statement, Object parameter, String mapKey, RowBounds rowBounds) {final List list = selectList (statement, parameter, rowBounds); final DefaultMapResultHandler mapResultHandler = new DefaultMapResultHandler (mapKey, configuration.getObjectFactory (), configuration.getObjectWrapperFactory ()); final DefaultResultContext context = new DefaultResultContext (); for (Object o: list) {context.nextResultObject (o); mapResultHandler.handleResult (context);} Map selectedMap = mapResultHandler.getMappedResults (); return selectedMap }......}
The selectMap method is actually further processed after selectList, getting the result handler of type DefaultMapResultHandler through mapKey, then traversing the list, calling handler's handleResult to process each result into map, and finally returning map.
Package org.apache.ibatis.executor.result;public class DefaultMapResultHandler implements ResultHandler {private final Map mappedResults;...... Public void handleResult (ResultContext context) {/ / TODO is that assignment always true? Final V value = (V) context.getResultObject (); final MetaObject mo = MetaObject.forObject (value, objectFactory, objectWrapperFactory); / / TODO is that assignment always true? Final K key = (K) mo.getValue (mapKey); mappedResults.put (key, value);}.}
You can see that DefaultMapResultHandler fetches K from metadata through mapKey, and then mappedResults.put (key, value) is put into map.
Thinking
@ MapKey is processed after the query is completed. In fact, we can also write our own logic to convert List to Map, which can be done with a Lambda expression, as follows:
List list = userDao.selectByIdList (Arrays.asList); Map map = list.stream (). Collect (Collectors.toMap (User::getId, user-> user)); Mybatis @ MapKey analysis
Let's give an example.
@ Test public void testShouSelectStudentUsingMapperClass () {/ / waring uses him as the first test class try (SqlSession session = sqlMapper.openSession ()) {StudentMapper mapper = session.getMapper (StudentMapper.class); System.out.println (mapper.listStudentByIds (new int [] {1pm 2pm 3});} @ MapKey ("id") Map listStudentByIds (int [] ids); select * from t_student where id in # {item}
Result
1. What is the function of MapKey annotations
Mapkey can assemble the results of the query into Map,Map. Key is the field specified by @ MapKey, and Value is the entity class. As shown in the above figure
2. Source code analysis of MapKey
Or from the source code analysis of how he is implemented, to note that the MapKey is not written in the Xml, but marked on the method. So, for a XML file, he certainly doesn't operate when parsing the file. For Mapper annotation implementations, it is theoretically used for parsing, but compared to XML parsing, it should not be. To say a little more, think about Spring, which starts with XML, and finally uses annotations, and the function of annotations corresponds to that of XML, so when parsing how XML is parsed, it should be parsed when parsing annotations.
It's still the same old routine, take a look at it and see where he is referenced. As you can see from the picture below, one of the places used is MapperMethod and the other is MapperAnnotationBuilder. You just judge it in MapperAnnotationBuilder, and there is no substantive operation, so you don't have to worry about it here. Just look at the former.
1. MapperMethod's operation on MapKey
Those of you who have read the previous article must know where MapperMethod was created. This is created when the query of the mapper interface is called. The execution of the interface method will eventually call the execute method of this object
MapperMethod contains two objects, SqlCommand and MethodSignature, which refer to MapKey in MethodSignature.
Public MethodSignature (Configuration configuration, Class mapperInterface, Method method) {/ / judge the type of return value of this method Type resolvedReturnType = TypeParameterResolver.resolveReturnType (method, mapperInterface); if (resolvedReturnType instanceof Class) {this.returnType = (Class) resolvedReturnType;} else if (resolvedReturnType instanceof ParameterizedType) {this.returnType = (Class) ((ParameterizedType) resolvedReturnType). GetRawType ();} else {this.returnType = method.getReturnType () } / / whether the return value is empty this.returnsVoid = void.class.equals (this.returnType); / / whether it is a list or array this.returnsMany = configuration.getObjectFactory () .isCollection (this.returnType) | | this.returnType.isArray (); / / whether the return value returns a cursor this.returnsCursor = Cursor.class.equals (this.returnType) / / whether the return value is an Optional this.returnsOptional = Optional.class.equals (this.returnType); / / the key point is that it is determined that the return value is a MapKey, and the value of Value in MapKey will be assigned to MapKey this.mapKey = getMapKey (method); / / whether the return value is a map this.returnsMap = this.mapKey! = null; this.rowBoundsIndex = getUniqueParamIndex (method, RowBounds.class) This.resultHandlerIndex = getUniqueParamIndex (method, ResultHandler.class) / / find the value of the first parameter type ResultHandler in the method parameters / / here is the param comment in the processing method parameters. Note that there are two special parameters in the method parameters, RowBounds and ResultHandler / / the parameters specified by @ param will be judged, and these parameters will be combined into a map,key is the subscript, and value is the parameter specified by param, if there is no Use the method parameter name this.paramNameResolver = new ParamNameResolver (configuration, method) }
The most important thing in the above code is mapKey's assignment operator getMapKey. Let's see what it looks like.
Private String getMapKey (Method method) {String mapKey = null; if (Map.class.isAssignableFrom (method.getReturnType () {final MapKey mapKeyAnnotation = method.getAnnotation (MapKey.class); if (mapKeyAnnotation! = null) {mapKey = mapKeyAnnotation.value ();}} return mapKey;}
The above describes where the MapKey is parsed, and the following analysis of how Mapkey is applied, all aside, around the query. After the introduction above. The flow of the query is very clear, because the query is still an ordinary query, so MapKey will only send the function when the value is assembled. Let's take a look.
It's still the same old routine. Now that you've assigned a value to MethodSignature's mapKey, let's see where he is quoted.
There's nothing to see below. Look at the top. It's used in MapperMethod, so take a look.
/ / by looking at this name, you can see that this is an operation that executes a Map query: private Map executeForMap (SqlSession sqlSession, Object [] args) {Map result; Object param = method.convertArgsToSqlCommandParam (args); if (method.hasRowBounds ()) {RowBounds rowBounds = method.extractRowBounds (args); / / pass Map to sqlSession, then go straight down result = sqlSession.selectMap (command.getName (), param, method.getMapKey (), rowBounds). } else {result = sqlSession.selectMap (command.getName (), param, method.getMapKey ());} return result;}
Keep clicking, and you'll see this one below, where you pass mapKey to DefaultMapResultHandler to process the results of the query.
@ Override public Map selectMap (String statement, Object parameter, String mapKey, RowBounds rowBounds) {/ / this has been queried by final List
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.