zoukankan      html  css  js  c++  java
  • MyBatis

    单个参数:mybatis不会做特殊处理,
    #{参数名/任意名}:取出参数值。

    多个参数:mybatis会做特殊处理。
    多个参数会被封装成 一个map,
    key:param1...paramN,或者参数的索引也可以
    value:传入的参数值
    #{}就是从map中获取指定的key的值;

    异常:
    org.apache.ibatis.binding.BindingException:
    Parameter 'id' not found.
    Available parameters are [1, 0, param1, param2]
    操作:
    方法:public Employee getEmpByIdAndLastName(Integer id,String lastName);
    取值:#{id},#{lastName}

    【命名参数】:明确指定封装参数时map的key;@Param("id")
    多个参数会被封装成 一个map,
    key:使用@Param注解指定的值
    value:参数值
    #{指定的key}取出对应的参数值


    POJO:
    如果多个参数正好是我们业务逻辑的数据模型,我们就可以直接传入pojo;
    #{属性名}:取出传入的pojo的属性值

    Map:
    如果多个参数不是业务模型中的数据,没有对应的pojo,不经常使用,为了方便,我们也可以传入map
    #{key}:取出map中对应的值

    TO:
    如果多个参数不是业务模型中的数据,但是经常要使用,推荐来编写一个TO(Transfer Object)数据传输对象
    Page{
    int index;
    int size;
    }

    ========================思考================================
    public Employee getEmp(@Param("id")Integer id,String lastName);
    取值:id==>#{id/param1} lastName==>#{param2}

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

    ##特别注意:如果是Collection(List、Set)类型或者是数组,
    也会特殊处理。也是把传入的list或者数组封装在map中。
    key:Collection(collection),如果是List还可以使用这个key(list)
    数组(array)
    public Employee getEmpById(List<Integer> ids);
    取值:取出第一个id的值: #{list[0]}

    ========================结合源码,mybatis怎么处理参数==========================
    总结:参数多时会封装map,为了不混乱,我们可以使用@Param来指定封装时使用的key;
    #{key}就可以取出map中的值;

    (@Param("id")Integer id,@Param("lastName")String lastName);
    ParamNameResolver解析参数封装map的;
    //1、names:{0=id, 1=lastName};构造器的时候就确定好了

    确定流程:
    1.获取每个标了param注解的参数的@Param的值:id,lastName; 赋值给name;
    2.每次解析一个参数给map中保存信息:(key:参数索引,value:name的值)
    name的值:
    标注了param注解:注解的值
    没有标注:
    1.全局配置:useActualParamName(jdk1.8):name=参数名
    2.name=map.size();相当于当前元素的索引
    {0=id, 1=lastName,2=2}

    args【1,"Tom",'hello'】:

    public Object getNamedParams(Object[] args) {
    final int paramCount = names.size();
    //1、参数为null直接返回
    if (args == null || paramCount == 0) {
    return null;

    //2、如果只有一个元素,并且没有Param注解;args[0]:单个参数直接返回
    } else if (!hasParamAnnotation && paramCount == 1) {
    return args[names.firstKey()];

    //3、多个元素或者有Param标注
    } else {
    final Map<String, Object> param = new ParamMap<Object>();
    int i = 0;

    //4、遍历names集合;{0=id, 1=lastName,2=2}
    for (Map.Entry<Integer, String> entry : names.entrySet()) {

    //names集合的value作为key; names集合的key又作为取值的参考args[0]:args【1,"Tom"】:
    //eg:{id=args[0]:1,lastName=args[1]:Tom,2=args[2]}
    param.put(entry.getValue(), args[entry.getKey()]);


    // add generic param names (param1, param2, ...)param
    //额外的将每一个参数也保存到map中,使用新的key:param1...paramN
    //效果:有Param注解可以#{指定的key},或者#{param1}
    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;
    }
    }
    }
    ===========================参数值的获取======================================
    #{}:可以获取map中的值或者pojo对象属性的值;
    ${}:可以获取map中的值或者pojo对象属性的值;


    select * from tbl_employee where id=${id} and last_name=#{lastName}
    Preparing: select * from tbl_employee where id=2 and last_name=?
    区别:
    #{}:是以预编译的形式,将参数设置到sql语句中;PreparedStatement;防止sql注入
    ${}:取出的值直接拼装在sql语句中;会有安全问题;
    大多情况下,我们去参数的值都应该去使用#{};

    原生jdbc不支持占位符的地方我们就可以使用${}进行取值
    比如分表、排序。。。;按照年份分表拆分
    select * from ${year}_salary where xxx;
    select * from tbl_employee order by ${f_name} ${order}

    #{}:更丰富的用法:
    规定参数的一些规则:
    javaType、 jdbcType、 mode(存储过程)、 numericScale、
    resultMap、 typeHandler、 jdbcTypeName、 expression(未来准备支持的功能);

    jdbcType通常需要在某种特定的条件下被设置:
    在我们数据为null的时候,有些数据库可能不能识别mybatis对null的默认处理。比如Oracle(报错);

    JdbcType OTHER:无效的类型;因为mybatis对所有的null都映射的是原生Jdbc的OTHER类型,oracle不能正确处理;

    由于全局配置中:jdbcTypeForNull=OTHER;oracle不支持;两种办法
    1、#{email,jdbcType=OTHER};
    2、jdbcTypeForNull=NULL
    <setting name="jdbcTypeForNull" value="NULL"/>

    • 45
      •  1 //查询员工id'在给定集合中的
         2     public List<Employee> getEmpsByConditionForeach(@Param("ids")List<Integer> ids);
         3 
         4 <select id="getEmpsByConditionForeach" resultType="com.atguigu.mybatis.bean.Employee">
         5          select * from tbl_employee
         6          <!--
         7              collection:指定要遍历的集合:
         8                  list类型的参数会特殊处理封装在map中,map的key就叫list
         9              item:将当前遍历出的元素赋值给指定的变量
        10              separator:每个元素之间的分隔符
        11              open:遍历出所有结果拼接一个开始的字符
        12              close:遍历出所有结果拼接一个结束的字符
        13              index:索引。遍历list的时候是index就是索引,item就是当前值
        14                            遍历map的时候index表示的就是map的key,item就是map的值
        15              
        16              #{变量名}就能取出变量的值也就是当前遍历出的元素
        17            -->
        18          <foreach collection="ids" item="item_id" separator=","
        19              open="where id in(" close=")">
        20              #{item_id}
        21          </foreach>
        22      </select>
    • 48 动态sql_内置参数_parameter&_databaseId
     1  <!-- 两个内置参数:
     2          不只是方法传递过来的参数可以被用来判断,取值。。。
     3          mybatis默认还有两个内置参数:
     4          _parameter:代表整个参数
     5              单个参数:_parameter就是这个参数
     6              多个参数:参数会被封装为一个map;_parameter就是代表这个map
     7          
     8          _databaseId:如果配置了databaseIdProvider标签。
     9              _databaseId就是代表当前数据库的别名oracle
    10       -->
    11       
    12       <!--public List<Employee> getEmpsTestInnerParameter(Employee employee);  -->
    13       <select id="getEmpsTestInnerParameter" resultType="com.atguigu.mybatis.bean.Employee">
    14               <!-- bind:可以将OGNL表达式的值绑定到一个变量中,方便后来引用这个变量的值 -->
    15               <bind name="_lastName" value="'%'+lastName+'%'"/>
    16               <if test="_databaseId=='mysql'">
    17                   select * from tbl_employee
    18                   <if test="_parameter!=null">
    19                       where last_name like #{lastName}
    20                   </if>
    21               </if>
    22               <if test="_databaseId=='oracle'">
    23                   select * from employees
    24                   <if test="_parameter!=null">
    25                       where last_name like #{_parameter.lastName}
    26                   </if>
    27               </if>
    28       </select>

    49

     1      <!-- 批量保存 -->
     2      <!--public void addEmps(@Param("emps")List<Employee> emps);  -->
     3      <!--MySQL下批量保存:可以foreach遍历   mysql支持values(),(),()语法-->
     4     <insert id="addEmps">
     5          insert into tbl_employee(
     6              <include refid="insertColumn"></include>
     7          ) 
     8         values
     9         <foreach collection="emps" item="emp" separator=",">
    10             (#{emp.lastName},#{emp.email},#{emp.gender},#{emp.dept.id})
    11         </foreach>
    12      </insert><!--   -->
    13      
    14      <!-- 这种方式需要数据库连接属性allowMultiQueries=true;
    15          这种分号分隔多个sql可以用于其他的批量操作(删除,修改) -->
    16      <!-- <insert id="addEmps">
    17          <foreach collection="emps" item="emp" separator=";">
    18              insert into tbl_employee(last_name,email,gender,d_id)
    19              values(#{emp.lastName},#{emp.email},#{emp.gender},#{emp.dept.id})
    20          </foreach>
    21      </insert> -->
    22 
    23 
    24       <!-- 
    25           抽取可重用的sql片段。方便后面引用 
    26           1、sql抽取:经常将要查询的列名,或者插入用的列名抽取出来方便引用
    27           2、include来引用已经抽取的sql:
    28           3、include还可以自定义一些property,sql标签内部就能使用自定义的属性
    29                   include-property:取值的正确方式${prop},
    30                   #{不能使用这种方式}
    31       -->
    32       <sql id="insertColumn">
    33               <if test="_databaseId=='oracle'">
    34                   employee_id,last_name,email
    35               </if>
    36               <if test="_databaseId=='mysql'">
    37                   last_name,email,gender,d_id
    38               </if>
    39       </sql>
  • 相关阅读:
    PyQt作品 – PingTester – 多点Ping测试工具
    关于和技术人员交流的一二三
    Pyjamas Python Javascript Compiler, Desktop Widget Set and RIA Web Framework
    Hybrid Qt applications with PySide and Django
    pyjamas build AJAX apps in Python (like Google did for Java)
    PyQt 维基百科,自由的百科全书
    InfoQ:请问为什么仍要选择Java来处理后端的工作?
    Eric+PyQt打造完美的Python集成开发环境
    python select module select method introduce
    GUI Programming with Python: QT Edition
  • 原文地址:https://www.cnblogs.com/yunyouhua/p/8276163.html
Copyright © 2011-2022 走看看