MyBatis的学习(三):深入理解MyBatis的参数

MyBatis的学习(三):深入理解MyBatis的参数

动态代理:使用SqlSession,getMapper(dao接口.class)获取这个dao接口的对象。

传入参数:从java代码中把数据传入到mapper文件的sql语句中。

parameterType参数理解

写在mapper文件中的一个属性,表示dao接口中方法的参数的数据类型。

例如;StudentDao接口
public Student selectStudentById(Integer id)

测试:

  1. 编写dao接口查询单个学生
/**
     * 查询单个学生
     * @param id 学生id
     * @return 返回一个学生
     */
    public Student selectStudent(Integer id);
  1. 编写mapper文件
    
<select id="selectStudent" parameterType="java.lang.Integer" resultType="com.liang.entity.Student">
        select id,name,email,age from student where id = #{id}
select>
  1. 编写测试类
package com.liang;

import com.liang.dao.StudentDao;
import com.liang.entity.Student;
import com.liang.utils.MybatisUtils;
import org.apache.ibatis.session.SqlSession;
import org.junit.Test;

/**
 * @author liang
 * @date 编写日期: 2022/3/18 16:12
 */
public class TestParameter {

    @Test
    public void testParameterType(){
        //获取SqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        //动态代理获取dao的实体类
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        //执行语句
        Student student = null;
        student = dao.selectStudent(1005);
        //输出结果
        if(student!=null){
            System.out.println("查询到的学生是:"+student);
        }
        sqlSession.close();
    }
}
  1. 测试成功

MyBatis的学习(三):深入理解MyBatis的参数_第1张图片)]

传参类型

一个简单类型参数

mybatis把java的基本数据类型和String类型的参数都叫做简单类型。

在mapper文件中获取简单类型参数的一个值,使用**#{任意字符}**。

select id,name,email,age from student where id = #{id}

使用#{ }之后,mybatis执行sql语句是使用jdbc中的prePareStatement对象。

由mybatis执行下面的代码:

  1. mybatis创建Connection,prepareStatement对象

    String sql = "select id,name,email,age from student where id = ? ";
    prepareStatement pst = con.prepareStatement(sql);
    pst.SetInt(1,1001);
    
  2. 执行sql封装resultType="com.liang.entity.Student"这个对象

    ResultSet rs = ps.executeQuery();
    
    while(rs.next()){
    
    //从数据库表中取出一行数据,存到一个java对象是属性中
    
    }
    

使用@param传多个参数

当Dao接口方法有多个参数,需要通过名称使用参数,在方法形参面前加入@Param(“自定义参数名称”),mapper文件中使用#{自定义名称}

  • 举例子:根据用户名或年龄查找学生
  1. 编写Dao接口
    /**
     * 根据姓名年龄查询
     * @param name 姓名
     * @param age 年龄
     * @return
     */
    public List<Student> selectMulParam(@Param("myname") String name,@Param("myage") Integer age);
  1. mapper文件
    <select id="selectMulParam" resultType="com.liang.entity.Student">
        select id,name,email,age from student where name = #{myname} or age = #{myage}
    select>
  1. 测试方法
    @Test
    public void selectMulParam(){
        //获取SqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        //动态代理获取dao的实体类
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        //执行语句
        List<Student> students = dao.selectMulParam("小梁",18);
        //输出结果
        for (Student stu:students) {
            System.out.println("查询到的学生是:"+stu);
        }
        sqlSession.close();
    }
  1. 测试结果

MyBatis的学习(三):深入理解MyBatis的参数_第2张图片

使用对象传多个参数

使用java对象传参,java的属性值就是sql需要的参数值,每一个属性就是一个参数。

语法格式:#{property,javaType = java中的数据类型名,jdbcType=数据类型名称}

javaType 和jdbcType的类型mybatis可以检测出来,一般不需要设置,常用格式#{property}

  • 举列子:根据学生的姓名或年龄查询学生
  1. 编写保存姓名和年龄信息的类
package com.liang.vo;

/**
 * @author liang
 * @date 编写日期: 2022/3/18 17:18
 */
public class QueryParam {

    private String paramName;
    private Integer paramAge;

    public QueryParam() {
    }

    public QueryParam(String paramName, Integer paramAge) {
        this.paramName = paramName;
        this.paramAge = paramAge;
    }

    public String getParamName() {
        return paramName;
    }

    public void setParamName(String paramName) {
        this.paramName = paramName;
    }

    public Integer getParamAge() {
        return paramAge;
    }

    public void setParamAge(Integer paramAge) {
        this.paramAge = paramAge;
    }
}
  1. 编写dao接口,参数对象不唯一,也可以直接传Student
    /**
     * 使用java对象的属性值作为参数实际值
     * @param parm
     * @return
     */
    public List<Student> selectMulObject(QueryParam parm);
  1. 编写mapper文件
    
    <select id="selectMulObject" resultType="com.liang.entity.Student">
        
     select id,name,email,age from student where name = #{paramName} or age = #{paramAge}
    select>
  1. 编写测试方法
@Test
    public void selectMulObject(){
        //获取SqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        //动态代理获取dao的实体类
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        //执行语句
        List<Student> students = dao.selectMulObject(new QueryParam("张三",20));
        //输出结果
        for (Student stu:students) {
            System.out.println("查询到的学生是:"+stu);
        }
        sqlSession.close();
    }
  1. 测试结果

MyBatis的学习(三):深入理解MyBatis的参数_第3张图片

按位置传参(了解)

参数位置从零开始,引用参数语法#{arg位置},第一个参数是#{arg0},#第二个参数是#{arg1}

  1. 编写dao抽象方法
    /**
     * 使用位置传参
     * @param name 姓名
     * @param age 年龄
     * @return 返回查找到的学生
     */
    public List<Student> selectMulPosition(String name, Integer age);
  1. 编写mapper文件
    
    <select id="selectMulPosition" resultType="com.liang.entity.Student">
        select id,name,email,age from student where
        name = #{arg0} or age = #{arg1}
    select>
  1. 编写测试方法
@Test
    public void testSelectMulPosition(){
        //获取SqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        //动态代理获取dao的实体类
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        //执行语句
        List<Student> students = dao.selectMulPosition("李四",25);
        //输出结果
        for (Student stu:students) {
            System.out.println("查询到的学生是:"+stu);
        }
        sqlSession.close();
    }
  1. 测试结果

MyBatis的学习(三):深入理解MyBatis的参数_第4张图片

使用Map传多个参数(了解)

map集合可以存储多个值,使用map向mapper文件中一次传入多个参数。map集合使用String的key。Object类型的值存储参数,mapper文件使用**#{key}**引用参数值。

  1. 编写dao接口
    /**
     * 使用map传参
     * @param map
     * @return
     */
    public List<Student> selectMulMap(Map<String,Object> map);
  1. 编写mapper文件
    
    <select id="selectMulMap" resultType="com.liang.entity.Student">
        select id,name,email,age from student where
        name = #{myname} or age = #{age}
    select>
  1. 编写测试方法
    @Test
    public void testSelectMulMap(){
        //获取SqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        //动态代理获取dao的实体类
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        //执行语句
        Map<String, Object> map = new HashMap<>();
        map.put("myname","小梁");
        map.put("age",25);
        List<Student> students = dao.selectMulMap(map);
        //输出结果
        for (Student stu:students) {
            System.out.println("查询到的学生是:"+stu);
        }
        sqlSession.close();
    }
  1. 测试结果

MyBatis的学习(三):深入理解MyBatis的参数_第5张图片

#和$的比较

不同点

  • #是一个占位符号,告诉mybatis实际的参数传递,并使用mybatis的prepareStatement对象执行sql语句,#{…}代替sql语句的"?",这样更加安全,更迅速,通常是首选的方法。
  • $字符串替换,告诉mybatis使用$包含的"字符串"替换所在的位置,使用Statement把sql语句和${}的内容连接起来,主要用在替换表名,列名,不同列排序等操作。

小例子:根据id查询

    <select id="selectStudent" parameterType="java.lang.Integer" resultType="com.liang.entity.Student">
        select id,name,email,age from student where id = ${id}
    select>
    /**
     * 查询单个学生
     * @param id 学生id
     * @return 返回一个学生
     */
    public Student selectStudent(@Param("id") Integer id);
    @Test
    public void testParameterType(){
        //获取SqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        //动态代理获取dao的实体类
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        //执行语句
        Student student = null;
        student = dao.selectStudent(1005);
        //输出结果
        if(student!=null){
            System.out.println("查询到的学生是:"+student);
        }
        sqlSession.close();
    }

测试结果:

MyBatis的学习(三):深入理解MyBatis的参数_第6张图片

$存在安全隐患

如果一个程序如下:

<select id="selectStudentByName"  resultType="com.liang.entity.Student">
    select id,name,email,age from student where name = ${name}
select>
/**
 * 查询单个学生
 * @param name 学生姓名
 * @return 返回一个学生
 */
public Student selectStudentByName(@Param("name") String name);
@Test
public void testParameterType(){
    //获取SqlSession对象
    SqlSession sqlSession = MybatisUtils.getSqlSession();
    //动态代理获取dao的实体类
    StudentDao dao = sqlSession.getMapper(StudentDao.class);
    //执行语句
    Student student = null;
    student = dao.selectStudentByName("'李四';drop table student;");
    //输出结果
    if(student!=null){
        System.out.println("查询到的学生是:"+student);
    }
    sqlSession.close();
}

执行的时候sql语句就会变成:

select id,name,email,age from student where name = '李四';drop table student; 

会把整张表删掉!!!破坏数据等等!

一般用来替换表明或者列名,完全确定数据是安全的时候!

使用占位符号替换表名

  1. 编写dao接口
    /**
     * 根据列名排序
     * @param colName 姓名
     * @return
     */
    public List<Student> selectUser$Order(@Param("colName") String colName);
  1. mapper文件
    
    <select id="selectUser$Order" resultType="com.liang.entity.Student">
        select * from student order by ${colName}
    select>
  1. 测试类
    @Test
    public void testselectUser$Order(){
        //获取SqlSession对象
        SqlSession sqlSession = MybatisUtils.getSqlSession();
        //动态代理获取dao的实体类
        StudentDao dao = sqlSession.getMapper(StudentDao.class);
        List<Student> students = dao.selectUser$Order("name");
        for (Student stu:students) {
            System.out.println("查询到的学生是:"+stu);
        }
        sqlSession.close();
    }
  1. 根据姓名排序

MyBatis的学习(三):深入理解MyBatis的参数_第7张图片

  1. 根据email排序
List<Student> students = dao.selectUser$Order("email");

MyBatis的学习(三):深入理解MyBatis的参数_第8张图片

你可能感兴趣的:(javaweb,mybatis,intellij-idea,maven)