一、源码解析
一、useActualParamName配置
#{arg0}-#{argn}或者#{param1}-#{paramn}
#{0}-#{n}或者#{param1}-#{paramn}
二、源码解读(3.4.6)
在mapper的代理对象调用方法时,最终会是MapperMethod对象的execute方法。如下:
@Override public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { try { // 如果目标方法是Object类继承来的,直接调用目标方法 if (Object.class.equals(method.getDeclaringClass())) { return method.invoke(this, args); } else if (isDefaultMethod(method)) { return invokeDefaultMethod(proxy, method, args); } } catch (Throwable t) { throw ExceptionUtil.unwrapThrowable(t); } // 从缓存中获取MapperMethod 对象,如果没有就创建新的并添加 final MapperMethod mapperMethod = cachedMapperMethod(method); // 执行sql 语句 return mapperMethod.execute(sqlSession, args); }
MapperMethod的一个内部类MethodSignature封装了Mapper接口中定义的方法的相关信息。而MethodSignature的一个属性ParamNameResolver对象处理接口中定义的方法的参数列表。
ParamNameResolver 的属性
// 记录参数在参数列表中的位置索引与参数名称之间的对应关系 private final SortedMap
names; // 记录对应的方法参数是否使用了@Param注解 private boolean hasParamAnnotation;
ParamNameResolver的构造函数
/ * 通过反射读取方法中的信息,并初始化上面两个字段 * @param config * @param method */ public ParamNameResolver(Configuration config, Method method) { // 获取参数列表中每个参数的类型 final Class
[] paramTypes = method.getParameterTypes(); // 获取参数列表上的注解 @Param final Annotation[][] paramAnnotations = method.getParameterAnnotations(); // 该集合用于记录参数索引与参数名称的对应关系 final SortedMap
map = new TreeMap
(); int paramCount = paramAnnotations.length; // 遍历所有参数 for (int paramIndex = 0; paramIndex < paramCount; paramIndex++) { if (isSpecialParameter(paramTypes[paramIndex])) { // 如果参数是RowBounds类型或者ResultHandler类型,则跳过该参数 continue; } String name = null; // 遍历该参数上的注解集合 for (Annotation annotation : paramAnnotations[paramIndex]) { if (annotation instanceof Param) { // 获取@Param注解指定的参数名称 hasParamAnnotation = true; name = ((Param) annotation).value(); break; } } // 没有@Param注解的话 执行下面逻辑 if (name == null) { // useActualParamName==true时 即name = arg0 ... if (config.isUseActualParamName()) { name = getActualParamName(method, paramIndex); } if (name == null) {//useActualParamName == false是 即 name="0" ... // use the parameter index as the name ("0", "1", ...) // 使用参数的索引作为其名称 name = String.valueOf(map.size()); } } map.put(paramIndex, name); } names = Collections.unmodifiableSortedMap(map); }
names集合主要是在ParamNameResolver.getNamedParams方法中使用
/ * * @param args 用户传入的参数值列表 * @return */ public Object getNamedParams(Object[] args) { final int paramCount = names.size(); if (args == null || paramCount == 0) { return null; } else if (!hasParamAnnotation && paramCount == 1) {// 未使用@Param注解且参数列表只有一个 return args[names.firstKey()];//即args[0] 参数的值 } else { // 下面是为参数创建param+索引的格式作为默认参数名称 如:param1 下标从1开始 final Map
param = new ParamMap
二.使用@param参数注解
一、单一属性
service层示例
todoItemsMapper.selectItembyparam1(1,"medium")
dao层示例
List
selectItembyparam1(@Param("id") int userId,@Param("pty") String Priority);
xml映射对应示例
[{ "todoItemId": 2, "userId": 1, "todoItemTitle": "bbbb", "todoItemContent": "待办事项2", "priority": "medium", "creationDate": 00, "lastUpdateDate": 00, "comments": "bb" }, { "todoItemId": 4, "userId": 1, "todoItemTitle": "dddd", "todoItemContent": "待办事项4", "priority": "medium", "creationDate": 00, "lastUpdateDate": 00, "comments": "ddd" }]
二、JavaBean对象
一、单个javabean对象
service 层示例
CuxTodoItems items = new CuxTodoItems(); items.setUserId(1); items.setPriority("low"); List
itemsList = todoItemsMapper.selectItembyparam2(items); return itemsList;
dao层示例
List
selectItembyparam2(@Param("item") CuxTodoItems cuxTodoItems);
xml映射对应示例
[{ "todoItemId": 5, "userId": 1, "todoItemTitle": "eee", "todoItemContent": "待办事项5", "priority": "low", "creationDate": 00, "lastUpdateDate": 00, "comments": "ee" }, { "todoItemId": 6, "userId": 1, "todoItemTitle": "fffffffff", "todoItemContent": "ffffffffff", "priority": "low", "creationDate": 00, "lastUpdateDate": 00, "comments": "ffffffffffffffffffff" }]
二、多个javabean对象
service层
CuxTodoItems items = new CuxTodoItems(); items.setPriority("high"); CuxUsers users = new CuxUsers(); users.setUserId(2); List
itemsList = todoItemsMapper.selectItembyparam3(items,users);
dao层
List
selectItembyparam3(@Param("it") CuxTodoItems cuxTodoItems, @Param("us")CuxUsers user);
xml对应示例
[{ "todoItemId": 7, "userId": 2, "todoItemTitle": "ggg", "todoItemContent": "代办事项g", "priority": "high", "creationDate": 00, "lastUpdateDate": 00, "comments": "备注g" }]
三.不使用@param参数注解
一、单一属性
一、一个单一属性
service
todoItemsMapper.selectItembyparam4(2);
dao 层
List
selectItembyparam4( int userId);
xml对应示例
[{ "todoItemId": 7, "userId": 2, "todoItemTitle": "ggg", "todoItemContent": "代办事项g", "priority": "high", "creationDate": 00, "lastUpdateDate": 00, "comments": "备注g" }]
注意:当查询参数为一个单一属性且没有使用注解时xml中查询字段#{}内可以为任意值
二、多个单一属性
service层
todoItemsMapper.selectItembyparam5(1,"high");
dao层
List
selectItembyparam5( int userId,String Priority);
xml对应示例
[{ "todoItemId": 3, "userId": 1, "todoItemTitle": "ccc", "todoItemContent": "待办事项3", "priority": "high", "creationDate": 00, "lastUpdateDate": 00, "comments": "cc" }]
二、JavaBean对象
一、单个javabean对象
service层
CuxTodoItems items = new CuxTodoItems(); items.setUserId(2); items.setPriority("high"); List
itemsList = todoItemsMapper.selectItembyparam6(items);
dao层
List
selectItembyparam6( CuxTodoItems cuxTodoItems);
xml对应查询字段
[{ "todoItemId": 7, "userId": 2, "todoItemTitle": "ggg", "todoItemContent": "代办事项g", "priority": "high", "creationDate": 00, "lastUpdateDate": 00, "comments": "备注g" }]
注意:xml查询字段需要与javabean属性一致
二、多个javabean对象
service层
CuxTodoItems items = new CuxTodoItems(); items.setPriority("medium"); CuxUsers users = new CuxUsers(); users.setUserId(1); List
itemsList = todoItemsMapper.selectItembyparam7(items,users);
dao层
List
selectItembyparam7( CuxTodoItems cuxTodoItems, CuxUsers user);
xml对应查询
[{ "todoItemId": 2, "userId": 1, "todoItemTitle": "bbbb", "todoItemContent": "待办事项2", "priority": "medium", "creationDate": 00, "lastUpdateDate": 00, "comments": "bb" }, { "todoItemId": 4, "userId": 1, "todoItemTitle": "dddd", "todoItemContent": "待办事项4", "priority": "medium", "creationDate": 00, "lastUpdateDate": 00, "comments": "ddd" }]

四、总结:
1.如果接口方法有一个或多个参数,并且使用了@Param注解,若注解的为单一属性则sql语句中的参数用注解的value值,若为bean则sql语句中使用的参数注解的value.bean属性值
2.如果接口方法的参数只有一个,并且没有使用@Parma注解,若为单一属性,则sql语句直接使用任何名称均可,若为bean,则sql 语句中的参数直接为bean的属性值就行。
3.如果接口的方法有多个参数,并且没有使用@Parma注解,单一属性 时sql语句使用param1…paramn,bean时sql语句使用param1.属性值…paramn.属性值是不会错的。
发布者:全栈程序员-站长,转载请注明出处:https://javaforall.net/222049.html原文链接:https://javaforall.net
