• 03【MyBatis参数深入】


    三、MyBaits参数深入

    • parameterType: 输入参数。对应方法的形参。

    • resultType: 输出参数。表示方法的返回值类型。

    3.1 parameterType输入参数

    parameterType用于确定方法的形参,在mapper映射文件中,parameterType可写可不写;

    3.1.1 传递单个参数

    在传递单个参数时,mybatis不会做特殊处理,#{参数名/任意名}都可以取出参数值,

    接口:

    package com.dfbz.dao;
    
    import com.dfbz.entity.Emp;
    
    /**
     * @author lscl
     * @version 1.0
     * @intro:
     */
    public interface EmpDao {
        Emp findById(Integer id);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12

    dao接口映射:

    传递的是基本数据类型和String时,#{}里面的内容可以随便填写,取得都是形参中的值

    
    <select id="findById" parameterType="int" resultType="com.dfbz.entity.Emp">
        select * from emp where id=#{abc}
    select>
    
    • 1
    • 2
    • 3
    • 4

    测试:

    package com.dfbz.demo;
    
    import com.dfbz.dao.EmpDao;
    import com.dfbz.entity.Emp;
    import org.apache.ibatis.io.Resources;
    import org.apache.ibatis.session.SqlSession;
    import org.apache.ibatis.session.SqlSessionFactory;
    import org.apache.ibatis.session.SqlSessionFactoryBuilder;
    import org.junit.After;
    import org.junit.Before;
    import org.junit.Test;
    
    import java.io.IOException;
    import java.io.InputStream;
    
    /**
     * @author lscl
     * @version 1.0
     * @intro:
     */
    public class Demo01_MyBatis_ParameterType测试 {
    
        InputStream is;
        SqlSessionFactory sessionFactory;
        SqlSession session;
        EmpDao empDao;
    
        @Before
        public void init() throws Exception{
            is = Resources.getResourceAsStream("MyBatisConfig.xml");
            sessionFactory = new SqlSessionFactoryBuilder().build(is);
            session = sessionFactory.openSession(true);
            empDao = session.getMapper(EmpDao.class);
        }
    
        @After
        public void close() throws Exception{
            session.close();
            is.close();
        }
    
        @Test
        public void test1() throws IOException {
            Emp emp = empDao.findById(1);
            System.out.println(emp);
        }
    }
    
    • 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
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
    • 45
    • 46
    • 47

    3.1.2 传递多个参数时

    1)MyBatis提供的方式

    MyBaits在传递多个参数时会特殊处理,多个参数会被封装成 一个map,key从#{param1}一直到#{paramN},或者使用索引#{arg0}一直到#{argN}

    举例:创建dao接口,根据薪资范围查询

    • dao接口:
    List<Emp> findBySalaryScope(Double minSalary,Double maxSalary);
    List<Emp> findBySalaryScope2(Double minSalary,Double maxSalary);
    
    • 1
    • 2
    • 接口映射:
    <select id="findBySalaryScope" resultType="com.dfbz.entity.Emp">
    
        
        select * from emp where salary >= #{param1} and salary <= #{param2}
    select>
    
    
    <select id="findBySalaryScope2" resultType="com.dfbz.entity.Emp">
    
        
        select * from emp where salary >= #{arg0} and salary <= #{arg1}
    select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 测试类:
    @Test
    public void test2() throws IOException {
        List<Emp> empList1 = empDao.findBySalaryScope(6000.0, 7000.0);
        List<Emp> empList2 = empDao.findBySalaryScope2(6000.0, 7000.0);
    
        System.out.println(empList1);
        System.out.println(empList2);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    2)使用@param注解
    • 接口:
    /**
     * 使用@Param注解来确定参数名
     * @param minSalary
     * @param maxSalary
     * @return
     */
    List<Emp> findBySalaryScope3(@Param("minSalary") Double minSalary, @Param("maxSalary")Double maxSalary);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 接口映射:
    <select id="findBySalaryScope3" resultType="com.dfbz.entity.Emp">
        select * from emp where salary >= #{minSalary} and salary <= #{maxSalary}
    select>
    
    • 1
    • 2
    • 3

    3.1.3 CDATA批量转译

    
    <select id="findBySalaryScope3" resultType="com.dfbz.entity.Emp">
     #{minSalary} and salary < #{maxSalary} and name like #{emp.name}
        ]]>
    select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3.1.4 传递PoJo对象

    POJO(Plain Ordinary Java Object)简单的Java对象,实际就是普通JavaBean,pojo包装类型指的是一个对象里面又包含了另外一个对象。

    查询需求: 按照薪资的范围查询员工姓张的员工。

    1. 自定义一个查询类:Condition
    2. Condition中里面维护了User对象、还有薪资的开始、结束字段。
    1)定义Pojo对象
    package com.dfbz.entity;
    
    import lombok.AllArgsConstructor;
    import lombok.Data;
    import lombok.NoArgsConstructor;
    
    /**
     * @author lscl
     * @version 1.0
     * @intro:
     */
    @Data
    @AllArgsConstructor
    @NoArgsConstructor
    public class Condition {
        private Emp emp;
        private Double minSalary;
        private Double maxSalary;
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    2)dao接口
    // 根据条件查询
    List<Emp> findByCondition(Condition condition);
    
    • 1
    • 2
    3)接口映射
    
    <select id="findByCondition" parameterType="com.dfbz.entity.Condition" resultType="com.dfbz.entity.Emp">
        select * from emp where salary > #{minSalary} and salary < #{maxSalary} and name like #{emp.name}
    select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    4)测试
    @Test
    public void test3() throws IOException {
    
        Emp emp =new Emp();
        emp.setName("%张%");
    
        Condition condition=new Condition();
        // 设置emp
        condition.setEmp(emp);
    
        condition.setMinSalary(3000.0);
        condition.setMaxSalary(10000.0);
    
        // 根据条件查询
        List<Emp> empList = empDao.findByCondition(condition);
    
        empList.forEach(System.out::println);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    3.2 resultType输出参数

    3.2.1 简单类型

    1)dao接口:
    Long count();
    
    • 1
    2)接口映射:
    
    <select id="count" resultType="java.lang.Long">
        select count(1) from emp
    select>
    
    • 1
    • 2
    • 3
    • 4
    3)测试:
    @Test
    public void test4() throws IOException {
    
        Long count = empDao.count();
        System.out.println("查询到: " + count + "条记录");
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3.2.2 PoJo类型

    1)dao接口:
    /**
     * 根据员工姓名模糊查询
     * @param name
     * @return
     */
    List<Emp> findByNameLike(String name);
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    2)接口映射:
    
    <select id="findByNameLike" parameterType="java.lang.String" resultType="com.dfbz.entity.Emp">
        select * from emp where name like #{name}
    select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    3)测试:
    @Test
    public void test7() throws IOException {
    
        List<Emp> empList = empDao.findByNameLike("%小%");
        empList.forEach(System.out::println);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3.2.3 Map类型

    1)dao接口:
    // 根据id查询用户,结果集为hashmap
    Map<String,Object> findUserMapById(Integer id);
    
    // 查询所有用户,结果集为List
    List<Map<String,Object>> findAllUserMap();
    
    • 1
    • 2
    • 3
    • 4
    • 5
    2)接口映射:
    
    <select id="findUserMapById" resultType="HashMap">
        select * from emp where id=#{id}
    select>
    
    
    <select id="findAllUserMap" resultType="HashMap">
        select * from emp
    select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    3)测试:
    @Test
    public void test6() throws IOException {
    
        Map<String, Object> userMap = empDao.findUserMapById(1);
    
        System.out.println(userMap);
    
        List<Map<String, Object>> userMapAll = empDao.findAllUserMap();
        System.out.println(userMapAll);
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10

    3.3 resultMap输出参数

    前面通过resultType作为输出参数,可以把查询的结果,自动封装为对象。但是,有要求,数据库中的列名称,要与对象的属性一致。否则,不能正确封装数据。此时,可以使用resultMap解决; 设置列与属性的映射关系。

    默认情况下,查询封装的结果集表的列名必须和属性名一模一样(默认情况下驼峰命名也不行)

    可以在SqlMapConfig.xml配置文件中开启驼峰映射:

    <settings>
        
        <setting name="logImpl" value="STDOUT_LOGGING"/>
        
        <setting name="mapUnderscoreToCamelCase" value="true"/>
    settings>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    3.3.1 接口

    List<Emp> findAllEmp();
    
    • 1

    3.3.2 接口映射

    
    <resultMap id="empResultMap" type="com.dfbz.entity.Emp">
        <id property="id" column="id_">id>
        <result property="name" column="name_">result>
        <result property="age" column="age_">result>
        <result property="salary" column="salary_">result>
        <result property="addr" column="addr_">result>
    resultMap>
    <select id="findAllEmp" resultMap="empResultMap">
        select id id_,name name_,age age_,salary salary_,addr addr_ from emp
    select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19

    3.3.3 测试类

    @Test
    public void test8() throws IOException {
    
        List<Emp> empList = empDao.findAllEmp();
        for (Emp emp : empList) {
            System.out.println(emp);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8

    3.4 SQL注入问题

    在MyBatis传值的过程中,除了可以使用#{}获取值之外,还可以使用${}获取值:

    定义一个接口:

    List<Emp> findByName2(String name);
    
    • 1

    接口映射:

    
    
    
    <select id="findByUsername2" parameterType="java.lang.String" resultType="com.dfbz.entity.Emp">
        select * from emp where name like '${value}'
    select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    注意:使用${}时,里面必须填写value;在新版本可以写任意的值

    根据测试结果,不能防止sql注入。

    // 不能防止SQL注入
    List<Emp> empList = userDao.findByNameLike2("abc' or 1=1 -- ");
    
    // 能防止SQL注入
    List<Emp> empList = userDao.findByNameLike("abc' or 1=1 -- ");
    
    • 1
    • 2
    • 3
    • 4
    • 5

    3.5 #{}和${}的区别

    既然#{}${}好那么多,那为什么还要有${}这个东西存在呢?干脆都用#{}不就万事大吉吗?其实不是的,${}也有用武之地;

    • 场景举例:
    
    <select id="test1" parameterType="java.lang.String" resultType="com.dfbz.entity.Emp">
        select * from ${value}
    select>
    
    
    <select id="test1" parameterType="java.lang.String" resultType="com.dfbz.entity.Emp">
        ${value}
    select>
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 测试代码:
    @Test
    public void test10() throws IOException {
    
        List<Emp> empList = empDao.test1("emp");
        for (Emp emp : empList) {
            System.out.println(emp);
        }
    }
    
    
    @Test
    public void test11() throws IOException {
    
        List<Emp> empList = empDao.test1("select * from emp");
        for (Emp emp : empList) {
            System.out.println(emp);
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    总结:

    1)#{}会对特殊字符进行过滤,传递的参数不会参与SQL语句的生成。

    2)${}不会对特殊字符进行过滤,传递的参数本就是用于参与SQL语句生成的,因此会出现SQL注入的问题

    3)${}里面必须填写value(新版本已经改进),#{}随意

  • 相关阅读:
    PCI认证:为什么它对你的业务至关重要,以及如何成功获得认证?
    制造业仓库很乱,该如何有效的管理呢?
    盲签名(Blind Signature)--RSA方案
    刷题《剑指Offer》day12
    PHP保存时自动删除末尾的空格,phpstorm自动删除空白字符串
    Java知识点之单例模式
    美团一面面经及详细答案
    PRML一书中关于贝叶斯曲线拟合结论的推导细节
    17:00面试,17:09就出来了 ,问的实在是太...
    K_A02_005 基于单片机驱动数码管 LED 按键模块(TM1638) 流水灯 0-7 按键值显示
  • 原文地址:https://blog.csdn.net/Bb15070047748/article/details/127877412