Mybatis框架----->(4)深入理解传入映射文件的参数的各种方法和‘#’和‘$’符的区别

一、Mybatis传递参数

  • 意思是说从Java代码中把参数传到映射文件中,下面介绍几种常用的传参方法:
1、一个简单参数
  • Dao接口中的方法只有一个简单类型的参数,使用占位符#{任意字符}
  • 所谓简单类型:Java的基本类型和String

下面每种方法都介绍一种例子方便理解

(1)在接口中定义一个按id值查询数据表的方法
Student selectStudenById(Integer id);
(2)映射文件
<select id="selectStudenById" resultType="com.hcz.entity.Student">
    select * from student where id=#{studentId}
</select>

注意:

1、这里#{studentId}里面的值是自定义的变量名称,和方法参数名无关
2、这里使用#{ }之后,mybatis执行SQL语句使用的是jdbc中的PrepareStatement对象
3、由mybatis创建Connection,PrepareStatement对象

String sql = "select * from student where id=?";
PrepareStatement ps = conn.prepareStaetment(sql);
ps.setInt(1,1002);

4.执行sql封装为“com.hcz.dao.Student”这个对象

ResultSet rs = ps.executeQuery();
Student student = null;
while(rs.next){
    //从数据库取表的一行数据,存到一个java对象属性中
    student = new Student();
    student.setId(rs.getId("id"));
    student.setName(rs.getString("name"));
    student.setEmail(rs.getString("email"));
    student.setAge(rs.getInt("age"));
}
return student;//给了dao方法调用的返回值;Student student = dao. selectStudenById(1003);
(3)定义测试方法
@Test
public void testSelectStudents(){
    /**
     * 使用mybatis的动态代理机制,使用SqlSession.getMapper(dao接口)
     * getMapper能获取dao接口对应的实现类对象
     */
    SqlSession sqlSession = MyBatisUtil.getSqlSession();
    StudentDao dao = sqlSession.getMapper(StudentDao.class);
    //调用dao的方法,执行数据库的操作
    Student student = dao.selectStudenById(1003);
    System.out.println("学生="+student);
}
(4)执行结果

在这里插入图片描述

2、多个参数(使用@Param名称参数)
  • 当dao接口方法中有多个参数,在方法形参前面加入@Param(“自定义参数名”),而映射文件中则使用#{“自定义参数名”}
(1)在接口中定义一个方法
List<Student> selectMulitParam(@Param("myname") String name,
                                @Param("myage") Integer age);
(2)映射文件
<select id="selectMulitParam" resultType="com.hcz.entity.Student">
    select * from student where name=#{myname} or age=#{myage}
</select>

注意:

这里#{ }里面的值为@Param自定义的参数名

(3)定义测试方法
@Test
public void testSelectMulitParam(){
    SqlSession sqlSession = MyBatisUtil.getSqlSession();
    StudentDao dao = sqlSession.getMapper(StudentDao.class);
    List<Student> studentList = dao.selectMulitParam("李四", 28);
    for (Student student: studentList){
        System.out.println("学生="+student);
    }
}
(4)执行结果

在这里插入图片描述

3、多个参数(使用Java对象作为参数)
  • 使用Java对象传递参数,Java对象的属性值就是SQL语句需要的参数值
(1)在接口中定义一个方法
List<Student> selectMultiStudent(Student student);
(2)映射文件
<select id="selectMultiStudent" resultType="com.hcz.entity.Student">
    select * from student where name=#{name}
    or age=#{age}
</select>
(3)定义测试方法
@Test
public void testSelectMulitStudent(){
    SqlSession sqlSession = MyBatisUtil.getSqlSession();
    StudentDao dao = sqlSession.getMapper(StudentDao.class);
    Student student = new Student();
    student.setName("李四");
    student.setAge(36);
    List<Student> studentList = dao.selectMultiStudent(student);
    for (Student stu: studentList){
        System.out.println("学生="+stu);
    }
}
(4)执行结果

在这里插入图片描述

4、多个参数(按位置传递参数)
  • 参数位置从0开始,mybatis-3.4之前的版本使用#{0},#{1}方式, 从 mybatis3.4开始使用#{arg0},#{arg1}方式
(1)在接口中定义一个方法
List<Student> selectMultiPosition(String name,Integer age);
(2)映射文件
<select id="selectMultiPosition" resultType="com.hcz.entity.Student">
    select * from student where name=#{arg0}
    or age=#{arg1}
</select>
(3)定义测试方法
@Test
public void testSelectMulitPosition(){
    SqlSession sqlSession = MyBatisUtil.getSqlSession();
    StudentDao dao = sqlSession.getMapper(StudentDao.class);
    List<Student> studentList = dao.selectMultiPosition("李四",28);
    for (Student stu: studentList){
        System.out.println("学生="+stu);
    }
}
(4)执行结果

在这里插入图片描述

5、多个参数(使用Map传递参数,可读性比较差)
  • Map集合使用String的key,Object类型的值存储参数。映射文件使用#{key} 引用参数
(1)在接口中定义一个方法
List<Student> selectMultiByMap(Map<String,Object> map);
(2)映射文件
<select id="selectMultiByMap" resultType="com.hcz.entity.Student">
    select * from student where name=#{myname}
    or age=#{myage}
</select>
(3)定义测试方法
@Test
public void testSelectMultiMap(){
    SqlSession sqlSession = MyBatisUtil.getSqlSession();
    StudentDao dao = sqlSession.getMapper(StudentDao.class);
    Map<String,Object> data = new HashMap<>();
    data.put("myname","李四");// #{myname}
    data.put("myage",28); // #{myage}
    List<Student> stuList = dao.selectMultiByMap(data);
    stuList.forEach( stu -> System.out.println(stu));
}
(4)执行结果

在这里插入图片描述

6、#和$的区别
(1)#:占位符,告诉 mybatis 使用实际的参数值代替。并使用 PrepareStatement 对象执行 sql 语句, #{…}代替sql 语句的“?”。这样做更安全,更迅速,通常也是首选做法,

例:

<select id="selectStudenById" resultType="com.hcz.entity.Student">
    select * from student where id=#{studentId}
</select>
Mybatis内部执行的是:
String sql = "select * from student where id=?";
PrepareStatement ps = conn.prepareStaetment(sql);
ps.setInt(1,1002);
这里的1002会替换掉#{studentId}
(2) $ :字符串替换,其主要是用包含的字符串替换所在的位置,使用 Statement 把 sql 语句和${ }的内容连接起来。主要用在替换表名,列名,不同列排序等操作。

例:

select * from student where id=${studentId}

$执行后的结果为:
select id,name, email,age from student where id=1001
相当于:
String sql=“select id,name, email,age from student where id=” + “1001”;

(3) 它们的区别
  • #使用 ?在sql语句中做站位的, 使用PreparedStatement执行sql,效率高
  • #能够避免sql注入,更安全
  • $不使用占位符,是字符串连接方式,使用Statement对象执行sql,效率低
  • $:可以替换表名或者列名。例:
  1. 在接口中定义一个方法
List<Student> selectUse$Order(@Param("colname") String colname
                                ,@Param("myname") String name);
  1. 映射文件
<select id="selectUse$Order" resultType="com.hcz.entity.Student">
    select * from student where ${colname}=#{myname}
</select>
  1. 执行后的SQL语句为:
select * from student where name=? 
  • $有sql注入的风险,缺乏安全性。例:
  1. 在接口中定义一个方法
List<Student> selectUse$(@Param("colname") String colname);
  1. 映射文件
<select id="selectUse$" resultType="com.hcz.entity.Student">
    select * from student where name =${colname}
</select>
  1. 执行后的SQL语句为:
select * from student where name ='李四';drop table student

二、思维大纲

在这里插入图片描述

如有不足之处请大家指正哈!

  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

@烟雨倾城ゝ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值