zoukankan      html  css  js  c++  java
  • 【mybatis源码学习】mybatis的参数处理

    一、mybatis的参数处理以及参数取值

    1、单个参数

    • mybatis不做任何处理

    • 取值方式:

      ​ #{参数名/任意名}

    <!-- Employee getEmpById(Integer id);  -->
    <select id="getEmpById" resultType="com.mxc.bean.Employee">
        select * from employee where id=#{id}
    </select>
    View Code

    2、多个参数

    • mybatis会将多个参数自动封装为一个map

      ​ key:param1,…,paramN,也可以是0,…,N-1(即参数索引,N是参数的个数)

      ​ value:参数值

    • 取值方式:

      ​ #{上述的key}

    <!-- Employee getEmpByIdAndLastName(Integer id, String lastName);  -->
    <select id="getEmpByIdAndLastName" resultType="com.mxc.bean.Employee">
        select * from employee where id=#{param1} and last_name=#{param2}
    </select>
    View Code

    为多个参数指定明确的key

    • @Param注解可以为参数指定一个明确的key,方便在sql中取参数值

    • 取值方式:

      ​ #{@Param注解指定的key}

    <!-- Employee getEmpByIdAndLastName(@Param("id")Integer id, @Param("lastName")String lastName);  -->
    <select id="getEmpByIdAndLastName" resultType="com.mxc.bean.Employee">
        select * from employee where id=#{id} and last_name=#{lastName}
    </select>
    View Code

    参数多时会封装map,为了取参数值方便,使用@Param来指定封装时使用的key

    3、参数是一个POJO

    • 若多个参数刚好是一个POJO中的属性值,可以直接传入一个POJO

    • 取值方式:

      ​ #{属性名}

    <!-- Employee getEmpByIdAndLastName(Employee emp);  -->
    <select id="getEmpByIdAndLastName" resultType="com.mxc.bean.Employee">
        select * from employee where id=#{id} and last_name=#{lastName}
    </select>
    View Code

    4、参数是一个Map

    • 若多个参数不是某一个POJO的属性,可以封装为一个Map

    • 取值方式:

      ​ #{Map的key}

    <!-- 
        Employee getEmpByIdAndLastName(Map<String, Object> map); 
        map:
            Map<String, Object> map = new HashMap<>();
            map.put("id", 1);
            map.put("lastName", "mxc");
    -->
    <select id="getEmpByIdAndLastName" resultType="com.mxc.bean.Employee">
        select * from employee where id=#{id} and last_name=#{lastName}
    </select>
    View Code

    小试牛刀

    Employee getEmp(@Param("id")Integer id,String lastName);
    // 取值:id=>#{id/param1},lastName=>#{param2}
    
    Employee getEmp(Integer id,@Param("e")Employee emp);
    // 取值:id=>#{param1},lastName => #{param2.lastName/e.lastName}
    View Code

    #{}与${}的异同
    同:

    ​ 可以获取map中的值或者pojo对象属性的值

    异:

    #{}:是以预编译的形式,将参数设置到sql语句中,可以防止sql注入
    ${}:取出的值直接拼装在sql语句中,会有安全问题
    使用场景

    大多情况下,取参数的值使用#{}。在原生JDBC不支持占位符的地方可以使用${}。如按年份分表查询:select * from ${year}_salary;

    二、mybatis的参数处理的源码实现

    1、 内部数据结构

    package com.spring.test.service.mybatis;
    
    import org.apache.ibatis.builder.ParameterExpression;
    
    /**
     * 
     */
    public class paramHandler {
    
        public static void main(String[] args) {
            paramsTokenHandler();
        }
    
    
        /**
         * 方法名:List<User> queryList(String name, RowBounds rowBounds, int age, @Param("address") String addresss);
         * 参数内部映射:
         * MethodSignature.SortedMap<Integer, String> params
         *      参数列表的下标->参数名字(如果是@Param,则显示的是注解的value,否则为参数列表当前的除了RowBounds,ResultHandler以外的参数排名次数)
         *      0->0
         *      2->1
         *      3->address
         *
         * MethodSignature.convertArgsToSqlCommandParam(Object[] args)  返回:ParamMap
         *
         *     ParamMap内部存储如下:
         *     参数名字->参数下标
         *     0->name的值
         *     1->age的值
         *     address->addresss的值
         *
         *     param1->name的值
         *     param2->age的值
         *     param3->addresss的值
         *
         */
        public static void paramsToParamMap(){
    
        }
    
        /**
         * 例子:#{checkedTime,jdbcType=BIGINT,typeHandler=com.meituan.payment.fundsgateway.core.model.handler.DateForLongTypeHandler}
         */
        public static void paramsTokenHandler(){
            String token="checkedTime,jdbcType=BIGINT,typeHandler=com.meituan.payment.fundsgateway.core.model.handler.DateForLongTypeHandler";
            ParameterExpression parameterExpression=new ParameterExpression(token);
            String name=parameterExpression.get("property");
            System.out.println(name);
            String jdbcType=parameterExpression.get("jdbcType");
            System.out.println(jdbcType);
            String typeHandler=parameterExpression.get("typeHandler");
            System.out.println(typeHandler);
        }
    }
    View Code

    2、涉及到的特殊数据结构和算法

    org.apache.ibatis.scripting.defaults.DefaultParameterHandler

    =>通过sql解析的ParameterMapping循环遍历,从参数列表中获取指定的值,设置至sql语句中的?占位符。

     

    org.apache.ibatis.reflection.MetaObject

    =>将方法的参数列表包装成MetaObject,提供统一获取参数值的方法

     

    org.apache.ibatis.reflection.property.PropertyTokenizer

    =>根据sql语句占位符#{propertyName}中的propertyName去MetaObject中获取sql语句中的?的值。

    org.apache.ibatis.builder.SqlSourceBuilder

    org.apache.ibatis.builder.ParameterMappingTokenHandler

    org.apache.ibatis.parsing.GenericTokenParser

    org.apache.ibatis.builder.ParameterExpression

    =>将sql语句中#{}替换成?,并解析出List<ParameterMapping>

  • 相关阅读:
    Chromium GN构建工具的使用
    cef 不更新编译
    Debugging SSL on Linux
    chromium url 请求流程
    mim
    qt打包发布问题 缺失qt动态库
    qmake生成pro的make总失败。但是qt creator里面是好的
    qt 与 x11 头文件同时引用
    Ubuntu16安装GTK+2.0教程
    gcc编译静态库到自己的程序 解决在不同linux下因libc版本问题而不能运行 版本兼容问题
  • 原文地址:https://www.cnblogs.com/shangxiaofei/p/11442966.html
Copyright © 2011-2022 走看看