详解Mybatis之参数传递问题

简介: 详解Mybatis之参数传递问题

编译软件:IntelliJ IDEA 2019.2.4 x64

操作系统:win10 x64 位 家庭版

Maven版本:apache-maven-3.6.3

Mybatis版本:3.5.6

一. Mybatis中参数传递问题

1.1 单个普通参数传递

对于单个普通参数而言,只要它的数据类型是Java基本数据类型,包装类型,字符串类型等。请放心大胆的使用它去传递,因为MyBatis可直接使用这个参数,不需要经过任何处理。且不受参数名称约束,即你可以任意命名,但一般遵循见名知意的原则。

示例代码如下:

<select id="selectUsers" resultType="User">
  select id, username, password
  from users
  where id = #{id}
</select>

在上述代码中,"#{id}"中的id可以任意取名,并且在程序中传给id的参数,其数据类型只要是符合(Java基本数据类型,包装类型,字符串类型)其中之一,MyBatis可直接使用这个参数传入到sql语句中。

1.2 多个普通参数传递

对于任意多个参数而言,都会被MyBatis重新包装成一个Map传入。Map的key是param1,param2,或arg0,arg1。相应的value是参数的值。

用法案例:根据员工姓名与薪资在数据库中查找相应的员工信息

①先在Mapper接口定义根据员工姓名与薪资查找相应的员工信息的方法

代码示例如下:

//根据员工姓名与员工薪资来查查找相应的员工
public Employee selectEmployeeByNameandSalary(String lastName,double salary);

②在映射文件中定义相关的sql

<select id="selectEmployeeByNameandSalary" resultType="mybatis.pojo.Employee">
    select
        id,
        last_name ,
        email,
        salary
    from
        tbl_employee
    where last_name=#{param1}
          and
          salary=#{param2}
</select>

③测试

@Test
public void test2(){
    try {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //通过SqlSessionFactory对象调用openSession();
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //获取EmployeeMapper的代理对象
        EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
        Employee employee = employeeMapper.selectEmployeeByNameandSalary("李四", 9000);
        System.out.println(employee);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

1.3 命名参数

语法:

@Param(value="参数名")
@Param("参数名")

位置:

在XXXMapper接口中方法的形参前面声明

注意:

  • 它的底层封装的是Map结构
  • 命名参数支持参数【param1,param2,…】,但不支持【arg0,arg1…】

示例代码:

①Mapper接口对应代码的书写

//根据员工姓名与员工薪资来查查找相应的员工
public List<Employee> showEmpByName(@Param("lName") String lastName,@Param("salary") double salary);

②接口对应的映射文件中书写的sql

版本一(参数不使用param1,param2):

<select id="showEmpByName" resultType="mybatis.pojo.Employee">
    select
    id,
        last_name ,
        email,
        salary
    from
        tbl_employee
    //#{lName}里是Mapepr接口中对应方法形参中@Param("lName")里的值    
    where 
      last_name=#{lName}
    and
        salary=#{salary}
</select>

版本二(参数使用param1,param2):

<select id="showEmpByName" resultType="mybatis.pojo.Employee">
        select
            id,
            last_name ,
            email,
            salary
        from
            tbl_employee
        where
            last_name=#{param1}
        and
            salary=#{param2}
    </select>

版本三(参数使用arg0,arg1)

<select id="showEmpByName" resultType="mybatis.pojo.Employee">
        select
        id,
            last_name ,
            email,
            salary
        from
            tbl_employee
        where
            last_name=#{arg0}
        and
            salary=#{arg1}
    </select>

③测试

@Test
    public void test4(){
        try {
            //从当前类下寻找并加载mybatis-config.xml(核心配置文件)
            String resource = "mybatis-config.xml";
            InputStream inputStream = Resources.getResourceAsStream(resource);
            SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
            //通过SqlSessionFactory对象调用openSession()获取sqlsession对象
            SqlSession sqlSession = sqlSessionFactory.openSession();
            //sqlsession对象使用getMapper(),传入EmployeeMapper的反射对象以获取代理对象
            EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
            //使用其代理对象调用showEmpByName()通过员工姓名与薪资去查找相应的员工
            List<Employee> jack = employeeMapper.showEmpByName("jack", 9000);
            System.out.println(jack);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

1.4 POJO(java Bean)参数传递

Mybatis支持POJO [Java Bean】入参,参数key是POjO中的属性

用法案例:基于1.2小结中的用法案例,修改Mapper接口中该方法的形参为Employee类型,仅修改映射文件中相应的sql与测试代码

①修改Mapper接口中该方法的形参类型为Employee

代码示例如下:

//根据员工姓名与员工薪资来查查找相应的员工
public Employee selectEmployeeByNameandSalary(Employee employee);

②修改映射文件中相应的sql

<select id="selectEmployeeByNameandSalary" resultType="mybatis.pojo.Employee">
    select
        id,
        last_name ,
        email,
        salary
    from
      tbl_employee
    where 
      last_name=#{lastName}
   and
      salary=#{salary}
</select>

③测试

@Test
public void test3(){
    try {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //通过SqlSessionFactory对象调用openSession();
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //获取EmployeeMapper的代理对象
        EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
        Employee employee=new Employee();
        employee.setSalary(5600.0);
        employee.setLastName("jack");
        Employee jack = employeeMapper.selectEmployeeByNameandSalary(employee);
        System.out.println(jack);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

1.5 Map参数传递

Mybatis支持Map集合类型的元素直接入参,map的key是参数的key

注意:

Mybatis不支持方法重载,因为在Mybatis中xxxMapper接口对应的映射文件中若存在相同方法的sql,则其id值不能保持唯一性,会发生冲突

用法案例:基于1.2节的案例,这次使用Map集合作为形参传入,在对应的映射文件中书写相应的sql并测试

代码示例如下:

①使用Map集合作为形参传入

//根据员工姓名与员工薪资来查查找相应的员工
public List<Employee> showEmpByMap(Map<String,Object> map);

②在对应的映射文件中书写相应的sql

<select id="showEmpByMap" resultType="mybatis.pojo.Employee">
    select
        id,
        last_name ,
        email,
        salary
    from
    tbl_employee
    where last_name=#{lastName} and  salary=#{salary}
</select>

③测试

@Test
public void test5() {
    try {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //通过SqlSessionFactory对象调用openSession();
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //获取EmployeeMapper的代理对象
        EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
        Map<String,Object> map=new HashMap<>();
        map.put("lastName","jack");
        map.put("salary",5600);
        List<Employee> jack = employeeMapper.showEmpByMap(map);
        System.out.println(jack);
    } catch (IOException e) {
        e.printStackTrace();
    }
}

1.6 Collection ,List & Array等参数传递

当传入的参数数据类型为 Collection ,List 或Array等,在对应映射文件的相应sql部分可直接使用mybatis对应的内置自定义类型别名(collection、list、array)传入,亦可使用命名参数自定义名称。

用法案例:通过多个id获取员工的信息 【EmpIds:员工id的集合】

代码示例如下:

a.在EmployeeMapper接口定义相应的方法

/**
 * 通过多个id获取员工的信息 【EmpIds:员工id的集合】
 * @param EmpIds
 * @return
 */
public List<Employee> selectEmpByIds(@Param("ids") List<Integer> EmpIds);

b.在EmployeeMapper接口对应的映射文件中定义相应的sql

<select id="selectEmpByIds" resultType="employee">
        SELECT
            `id`,
            `last_name`,
            `email`,
            `salary`,
            `dept_id`
        FROM
            `tbl_employee`
        <where>
            `id` in
            (
            <foreach collection="ids" item="id" separator=",">
                #{id}
            </foreach>
            )
        </where>
    </select>

c.测试

@Test
public void test04(){
    try {
        String resource = "mybatis-config.xml";
        InputStream inputStream = Resources.getResourceAsStream(resource);
        SqlSessionFactory sqlSessionFactory = new SqlSessionFactoryBuilder().build(inputStream);
        //通过SqlSessionFactory对象调用openSession();
        SqlSession sqlSession = sqlSessionFactory.openSession();
        //获取EmployeeMapper的代理对象
        EmployeeMapper employeeMapper = sqlSession.getMapper(EmployeeMapper.class);
        List<Employee> employees = employeeMapper.selectEmpByOneOpr(1);
        System.out.println(employees);
    } catch (IOException e) {
        e.printStackTrace();
    }
}


二. Mybatis参数传递中#与$的使用问题

2.1 #与$的区别

  • #底层执行SQL语句的对象,使用PreparedStatementd,预编译SQL,防止SQL注入安全隐患,相对比较安全。
  • $底层执行SQL语句的对象使用Statementi对象,未解决SQL注入安全隐患,相对不安全。

2.2 #与$的使用场景

以查询SQL为例:

select col,col2 from table1 where col=? and col2=?group by? order by?limit?,?

使用场景:

  • “#”使用场景:在上述Sql中的占位符位置均可以使用#
  • “$”使用场景:#解决不了的参数传递问题,均可以交给$处理【如form动态表格】

示例代码如下:

public List<Employee> selectEmpByDynamitTable(@Param("tblName")String tblName);
<select id="selectEmpByDynamitTable" resultType="employee">
  SELECT
        id,
        last_name,
        email,
        salary
  FROM
    ${tb1Name}
</select>

附注:

在 Mybatis 中,$ 符号也是用于访问各种参数、变量等的值和信息的符号,主要用于动态 SQL 的构建和参数传递等场景中,例如:

  • ${variable}:用于插入变量或者表名/列名等的动态语句部分
  • #{parameter}:用于占位符参数的预编译语句
  • $方法名():用于调用 SQL 片段中定义的方法并返回结果

为什么说${variable}主要用于插入动态语句的部分?

解析不同:

  • ${variable}它是将传入的参数值直接显示在原来的sql语句中,且不加任何引号
    例如slect * from users where id=v a r i a b l e ,传入 {variable},传入variable,传入{1} => id=1
    代码示例如下:
<select id="showEmpByMap" resultType="mybatis.pojo.Employee">
        select
            id,
            last_name ,
            email,
            salary
        from
        tbl_employee
        where last_name=${lastName} and  salary=${salary}
    </select>

  • #{variable}是将传入的参数值当成一个字符串且加双引号显示
    例如slect * from users where id=v a r i a b l e ,传入 {variable},传入variable,传入{1} => id=“1”
    代码示例如下:
<select id="showEmpByMap" resultType="mybatis.pojo.Employee">
        select
            id,
            last_name ,
            email,
            salary
        from
        tbl_employee
        where last_name=#{lastName} and  salary=#{salary}
    </select>
相关文章
|
SQL Java 数据库连接
Mybatis实战练习六【批量删除&Mybatis参数传递】(下)
Mybatis实战练习六【批量删除&Mybatis参数传递】
|
SQL 存储 Java
Mybatis实战练习六【批量删除&Mybatis参数传递】(上)
Mybatis实战练习六【批量删除&Mybatis参数传递】
|
Java 数据库连接 mybatis
MyBatis参数传递
MyBatis参数传递
67 0
|
SQL XML 小程序
mybatis参数传递 -- Mybatis快速入门保姆级教程(三)
mybatis参数传递 -- Mybatis快速入门保姆级教程(三)
12080 13
|
SQL Java 数据库连接
mybatis多参数传递报错问题分析+硬核mybatis底层源码分析+@Param注解+图文实战环境分析【4500字详解打通,没有比这更详细的了!】(二)
mybatis多参数传递报错问题分析+硬核mybatis底层源码分析+@Param注解+图文实战环境分析【4500字详解打通,没有比这更详细的了!】
168 0
|
SQL Java 数据库连接
【MyBatis】day02参数传递和映射(下)
【MyBatis】day02参数传递和映射(下)
76 0
|
SQL 存储 缓存
【MyBatis】day02参数传递和映射(上)
【MyBatis】day02参数传递和映射
85 0
|
SQL 存储 Java
mybatis多参数传递报错问题分析+硬核mybatis底层源码分析+@Param注解+图文实战环境分析【4500字详解打通,没有比这更详细的了!】(一)
mybatis多参数传递报错问题分析+硬核mybatis底层源码分析+@Param注解+图文实战环境分析【4500字详解打通,没有比这更详细的了!】
529 0
|
XML SQL Java
mybatis开发要点-insert主键ID获取和多参数传递
mybatis开发要点-insert主键ID获取和多参数传递
200 0
|
XML SQL Java
mybatis学习(24):分页2 多参数传递(使用注解)
mybatis学习(24):分页2 多参数传递(使用注解)
105 0
mybatis学习(24):分页2 多参数传递(使用注解)