Mybatis多个参数传递名称可变源码解读源码解读

11.多个参数传递名称可变源码解读源码解读

  //接口方法 
public Dept selectDeptByIdAndName(@Param("id") int id , @Param("param2") String dName);

//xmlsql语句
    <select id="selectDeptByIdAndName" resultType="dept" >
                select
            id,
            dept_name,
            dept_loc
        from
            t_dept
        where
            id = #{id}
        and
            dept_name = #{param2}
    </select>

        //测试方法
        //查询多个普通参数
        Dept dept = mapper.selectDeptByIdAndName(2, "研发部");
		System.out.println("dept = " + dept);
        
        

//声名param字符串常量用于拼接param1,param2,...
	private static final String GENERIC_NAME_PREFIX = "param";
//Map集合  nams中存放的是传入的参数名,这个参数名用户自己定义的
//在传入多个参数时,如果在方法上使用了@Param()注解声名了别名,则names中存放的就是别名,如果没有存放别名,则names中就是,默认固定的
//字符args0,...或者param1,... .这个字符是根据在sql语句中的#{args0}来识别的
    private final SortedMap<Integer, String> names;
//判断是否使用了@Param注解,使用了则值为true ,没有使用则值为false
    private boolean hasParamAnnotation;


public Object getNamedParams(Object[] args) {
    	//判断执行方法中传入了几个参数, paramCount = 2
        int paramCount = this.names.size();
    //判断有没有传入参数,没有则直接返回null
        if (args != null && paramCount != 0) {
            //如果没有使用@Param注解并且传入的参数个数只有一个则直接返回参数
            if (!this.hasParamAnnotation && paramCount == 1) {
                return args[(Integer)this.names.firstKey()];
            } else {
                //如果有多个参数,则声名一个Map集合用来存放参数
                Map<String, Object> param = new ParamMap();
                int i = 0;
				//利用迭代器,遍历names中数据,即参入参数的名字 <Map>names[0 : "id",1 : "dName"]
                for(Iterator var5 = this.names.entrySet().iterator(); var5.hasNext(); ++i) {
                    Entry<Integer, String> entry = (Entry)var5.next();
                     //args中存放的传入的形参数据,names中存放的是形参名:需要将args中的数据与names中的形参名一一对应
                    //entry.getValue() 取出的是id,(Integer)entry.getKey()取出是value对应的索引,就可以找到args对应的第几个参数和参数名一起存放到param中
                    param.put(entry.getValue(), args[(Integer)entry.getKey()]);
                    //拼接param[1,2..]
                    String genericParamName = "param" + String.valueOf(i + 1);
                    //如果没有则将paramN : names[N]的值加入map中
                    //如果有则不用添加
                    if (!this.names.containsValue(genericParamName)) {
                        param.put(genericParamName, args[(Integer)entry.getKey()]);
                    }
                }

                return param;
            }
        } else {
            return null;
        }
    }

结论

1. 在接口定义方法时@Param注解要么所有参数都加上,要么所有参数都不要加
2. 在接口xml文件中使用占位符时,要么所有占位符都用别名,要么所有占位符都用默认值argsN或者paramN
3. 在底层map封装时会根据@param注解名称作为key,将参数数据作为value值进行封装.
4. 通常会将注解名对应的数据封装之后再用paramN值封装一次数据,即一般有两个参数map中会有4条数据,如果注解名和paramN值相同,这不会重复添加,这时可能只有三条数据,
5. 因此传入一条数据对应了两个不同的key值 ,所以在传参时使用别名和使用默认的paramN和argsN时都能识别
posted @ 2022-06-23 17:08  一生要强的阿信  阅读(61)  评论(0)    收藏  举报