Blog

  • 首页

  • 关于

  • 标签

  • 分类

  • 归档

  • 搜索

Mybatis_参数处理过程

发表于 2019-08-15 分类于 Mybatis 阅读次数:
本文字数: 5.3k

Mybatis参数处理过程

测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
public class MybatisTest {

public SqlSessionFactory getSqlSessionFactory() throws IOException {
String resource = "mybatisconfig.xml";
InputStream inputStream = Resources.getResourceAsStream(resource);
SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
return sqlSessionFactory;
}
@Test
public void test1() throws IOException {
SqlSessionFactory sqlSessionFactory = getSqlSessionFactory();
SqlSession sqlSession = sqlSessionFactory.openSession();
TestMapper mapper = sqlSession.getMapper(TestMapper.class);
User user = mapper.selectUserById(20);
System.out.println(user);

List<User> userList = mapper.selectUserByNameAndId(20, "测试员一号");
System.out.println(userList);

}
}

mapper

1
2
3
4
public interface TestMapper {
User selectUserById(int id);
List<User> selectUserByNameAndId(@Param("id") int id,@Param("name") String name);
}

mapper映射

1
2
3
4
5
6
7
8
9
10
11
12
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.yb.mapper.TestMapper">
<select id="selectUserById" resultType="com.yb.model.User">
select * from User where id = #{id}
</select>
<select id="selectUserByNameAndId" resultType="com.yb.model.User">
select * from USER where id = #{id} and realname = #{name}
</select>
</mapper>

源码分析

1
2
3
4
5
6
7
8
9
10
11
12
13
public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
try {
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);
}
final MapperMethod mapperMethod = cachedMapperMethod(method);
return mapperMethod.execute(sqlSession, args);
}

代理对象(MapperProxy)调用invoke()

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
public Object getNamedParams(Object[] args) {
final int paramCount = names.size();
//如果没有参数,直接返回null
if (args == null || paramCount == 0) {
return null;
}
//如果只有一个参数,而且没有用@Param注解,就直接返回
//因为names.firstKey() = 0
else if (!hasParamAnnotation && paramCount == 1) {
return args[names.firstKey()];
}
//当有多个参数时
else {
//创建一个map来存储参数
final Map<String, Object> param = new ParamMap<Object>();
int i = 0;
//遍历names
for (Map.Entry<Integer, String> entry : names.entrySet()) {
//把name中的Value作为key,把name中的key作为args的索引
//比如name={"0":"arg0"},那么arg0就是map的key,0为args的索引
param.put(entry.getValue(), args[entry.getKey()]);
// add generic param names (param1, param2, ...)
//创建默认的key:Param1,Param2...
final String genericParamName = GENERIC_NAME_PREFIX + String.valueOf(i + 1);
// ensure not to overwrite parameter named with @Param
if (!names.containsValue(genericParamName)) {
param.put(genericParamName, args[entry.getKey()]);
}
i++;
}
return param;
}
}

这里是进行参数的处理,其中names是一个map:{“0”=arg0},它是在构造函数中初始化的。代码如下

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
public ParamNameResolver(Configuration config, Method method) {
//获取所有参数
final Class<?>[] paramTypes = method.getParameterTypes();
//获取参数注解
final Annotation[][] paramAnnotations = method.getParameterAnnotations();
final SortedMap<Integer, String> map = new TreeMap<Integer, String>();
int paramCount = paramAnnotations.length;
// get names from @Param annotations
//遍历paramAnnotations,将带@Param注解的参数的值赋给name
for (int paramIndex = 0; paramIndex < paramCount; paramIndex++) {
if (isSpecialParameter(paramTypes[paramIndex])) {
// skip special parameters
continue;
}
String name = null;
for (Annotation annotation : paramAnnotations[paramIndex]) {
if (annotation instanceof Param) {
hasParamAnnotation = true;
name = ((Param) annotation).value();
break;
}
}
if (name == null) {
// @Param was not specified.
if (config.isUseActualParamName()) {
name = getActualParamName(method, paramIndex);
}
if (name == null) {
// use the parameter index as the name ("0", "1", ...)
// gcode issue #71
name = String.valueOf(map.size());
}
}
//用map保存name
map.put(paramIndex, name);
}
names = Collections.unmodifiableSortedMap(map);
}

当参数没有@Param注解时,names = {“0”=arg0,”1”=arg1,”2”=arg2…}
当参数有@Param注解时,names = {“0”=参数值1,”1”=参数值2…}
两个都有时,names = {“0”=arg0,”1”=arg1,”2”=参数值2..}
得到了names之后,就继续看getNamedParams

  • 没有参数,直接返回null
  • 如果只有一个参数,而且没有用@Param注解,就直接返回
  • 多个参数,最终结果如下
    param={“arg0”=参数值1,”arg1”=参数值2,”param1” = 参数值1,”param2” = 参数值2} (这是不带@Param注解的)
    param={“@Param的value值1”=参数值1,”@Param的value值2”=参数值2,”param1” = 参数值1,”param2” = 参数值2} (这是带@Param注解的)

所以当有多个参数时,mapper映射文件中就不可以直接用#{}来获取参数,因为参数都被封装为一个map了,需要根据封装后的map的key来获取参数


------ 已触及底线感谢您的阅读 ------
麻辣香锅不要辣 微信支付

微信支付

  • 本文作者: 麻辣香锅不要辣
  • 本文链接: https://http://ybhub.gitee.io/2019/08/15/Mybatis-参数处理过程/
  • 版权声明: 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
# Mybatis
Proxy
SpringBoot自动装配--ErrorMvcAutoConfiguration
  • 文章目录
  • 站点概览
麻辣香锅不要辣

麻辣香锅不要辣

21 日志
11 分类
20 标签
GitHub 简书
  1. 1. Mybatis参数处理过程
    1. 1.1. 测试类
    2. 1.2. mapper
    3. 1.3. mapper映射
    4. 1.4. 源码分析
© 2019 – 2020 麻辣香锅不要辣 | 站点总字数: 20.4k字
|
0%