4-传参

**从java代码中把数据传入mapper文件的sql语句,**就是传入参数。

parameterType

parameterType是

parameterType的值时java中数据类型的全限定类名或者是mybatis定义的别名。

例如:parameterType = "java.lang.Integer"parameterType = "int"

注意:parameterType不是必须的,mybatis能够通过反射机制发现接口参数的数据类型,所以可以没有。一般也不写。

传入一个简单类型参数

当DAO接口中的方法只有一个简单类型参数时(简单类型就是java的基本数据类型加上String),那么占位符#{任意字符}获取参数值,括号中的名称和方法参数名无关。可以是任意字符。

例子:

DAO接口中的方法:

1
public Student selectStudentById(Integer id);

映射文件的内容:

1
2
3
<select id="selectStudentById" resultType="org.example.domain.Student" >
select id, name, email, age from student where id = #{studentId}
</select>

可以看到,接口中方法参数名是id,映射文件中是studentId,并不相同。

多个参数-使用@Param(掌握)

当需要传入多个参数时,可以使用MyBatis提供的@Param注解。

使用方法:

  • DAO接口定义的方法中,在形参定义之前加上@Param(“自定义形参数名”)
  • 在映射文件中,占位符#{@Param定义的参数名}使用同样的名称来访问该参数

非常简单。

例子:
在DAO接口中定义方法:

1
2
public List<Student> selectStudentsByParams(@Param("studentName") String name,
@Param("studentId") Integer id);

在映射文件中编写具体sql语句:

1
2
3
<select id="selectStudentsByParams" resultType="org.example.domain.Student" >
select id, name, email, age from student where name = #{studentName} or id = #{studentId}
</select>

可以看到占位符使用的名称和@Param定义的名称相同。

MyBatis推荐使用这种方法。

多个参数-使用Java对象属性(掌握)

传入多个参数另一种方法就是传入一个Java对象,该对象的多个属性是数据库实际参数。

使用对象语法:#{属性名,javaType="类型名称",jdbcType="数据类型"}

​ 其中:

​ 属性名就是java对象中定义的变量名称;

​ javaType是java中的属性数据类型;

​ jdbcType是在数据库中的数据类型。

但是这样写,非常麻烦。

在实际开发中,一般采用简化模式:#{属性名},javaType和jdbcType的值MyBatis可以通过反射获取。

这种方法在之前的例子中已经使用过了,在此不再提供例子。

多个参数-使用位置(了解)

参数位置从0开始,引用参数的语法是:#{arg位置},例如第一个参数是#{arg0}、第二个是#{arg1},以此类推。

在MyBatis3.3之前版本使用#{0}#{1}方式,从3.4使用#{arg0}方式。

例子:

接口方法:

1
public List<Student> selectStudentsByParams(String name, Integer id);

映射文件:

1
2
3
<select id="selectStudentsByParams" resultType="org.example.domain.Student" >
select id, name, email, age from student where name = #{arg0} or id = #{arg1}
</select>

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

Map集合可以存储多个值,使用Map向映射文件一次传入多个参数,Mao集合使用String类型的key,Object类型的值存储value。

mapper文件中使用#{key}来引用对应参数值。

例子:
DAO接口中方法:

1
public List<Student> selectStudentsByParams(Map<String, Object> map);

映射文件:

1
2
3
<select id="selectStudentsByParams" resultType="org.example.domain.Student" >
select id, name, email, age from student where name = #{StudentName} or id = #{StudentId}
</select>

测试代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Test
public void testSelectStudentsByParams() {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);

Map<String,Object> map = new HashMap<>();
map.put("StudentName", "李四");
map.put("StudentId", 1004);


List<Student> list = dao.selectStudentsByParams(map);
for(Student stu : list) {
System.out.println(stu);
}
}

但这种方法不推荐使用,因为使用Map,不知道传入几个参数,也不知道每个参数的类型。

#和$-两个占位符比较

#:占位符,是告诉MyBatis用实际参数值来代替。#{…}代替sql语句中的"?"占位符,更安全,更迅速。

例如:
mapper文件中:

1
2
3
<select id="selectById" resultType="org.example.domain.Student">
select id, name, email, age from student where id=#{studentId}
</select>

在MyBatis内部执行其实使用的就是JDBC:

1
2
3
String sql = "select id, name, email age from student where id = ?"
PreparedStatement ps = conn.preparedStatement(sql);
ps.setInt(1, 1001);

所以where id = ? 就是 where id= #{studentId}

ps.setInt(1, 1001),1001会替换#{studentId}

$:这个使用的是字符串拼接的原理。

注意:$是字符串拼接,所以在传入参数时,要使用单引号括起来,例如:

List<Student> list = dao.selectStudentsByParams("'李四'", 1004);

$是字符串拼接,内部使用Statement来执行sql语句。可能会发生SQL注入,是有风险的。

所以通常,$不用来替换参数值,而是用来替换表名、列名、不同列排序等操作。

例子:使用不同列来进行查询

DAO接口定义方法:

1
public Student findByDiffField(@Param("col") String colName, @Param("value") Object value);

映射文件:

1
2
3
<select id="findByDiffField" resultType="org.example.domain.Student" >
select * from student where ${col} = #{value}
</select>

测试代码:

1
2
3
4
5
6
7
@Test
public void testFindByDiffField() {
SqlSession sqlSession = MyBatisUtils.getSqlSession();
StudentDao dao = sqlSession.getMapper(StudentDao.class);
Student student = dao.findByDiffField("name", "李四");
System.out.println(student);
}

可以使用任何一列来进行查询。

比较两种不同方法

$它可以替换#。但是原理是完全不同的,#是占位符。在内部使用PreparedStatement来执行sql语句;

使用#的控制台日志:

image-20201202124300046

使用$的控制台日志:

image-20201202124240371

可以看出区别,一个是?,一个直接把参数写入到了sql语句。

所以一个是占位符,一个是字符串拼接。

总上,#和$的区别:

  • #使用 ?能够在sql语句做占位符,使用PreparedStatement执行sql,效率高
  • #能够避免sql注入,更安全
  • $不使用占位符,是字符串连接方法,使用Statement对象执行sql,效率低
  • $有sql注入的风险,缺乏安全性
  • $可以替换表名和列名

4-传参
https://zhaoquaner.github.io/2022/05/11/MyBatis/4-传参/
更新于
2022年5月22日
许可协议