MyBatis参数传递
传参方式
1. 使用 #{}
占位符
这是 MyBatis 中最常用的参数传递方式。它将参数直接替换到 SQL 语句中的占位符位置。
单个参数:
<select id="selectUserById" resultType="User">
SELECT * FROM users WHERE id = #{id}
</select>
多个参数:
如果传递多个参数,可以按顺序使用 #{param1}
, #{param2}
, … 或者给参数命名。
<select id="selectUserByNameAndAge" resultType="User">
SELECT * FROM users WHERE name = #{name} AND age = #{age}
</select>
2. 使用 @Param
注解(推荐使用)
在接口方法中使用 @Param
注解可以给参数命名,这样在 SQL 映射文件中就可以使用这些名称。
User selectUserByNameAndAge(@Param("name") String name, @Param("age") int age);
对应的 XML:
<select id="selectUserByNameAndAge" resultType="User">
SELECT * FROM users WHERE name = #{name} AND age = #{age}
</select>
3. 使用 Map
可以将参数封装在一个 Map
或 POJO
(Plain Old Java Object)中,然后在 SQL 语句中通过键名或属性名来访问这些参数。
Map<String, Object> params = new HashMap<>();
params.put("name", "John");
params.put("age", 30);
对应的 XML:
<select id="selectUserByMap" resultType="User">
SELECT * FROM users WHERE name = #{name} AND age = #{age}
</select>
4. 使用 ${}
字符串替换
虽然不推荐使用,但 MyBatis 也支持使用 ${}
来进行字符串替换。这种方式容易导致 SQL 注入攻击,因此应该谨慎使用。
<select id="selectUserByName" resultType="User">
SELECT * FROM users WHERE name = '${name}'
</select>
注:
- 使用
#{}
时,MyBatis 会创建预处理语句(PreparedStatement),这有助于防止 SQL 注入。- 使用
${}
时,MyBatis 会直接将参数值拼接到 SQL 语句中,这可能会导致 SQL 注入风险。
参数不同的封装方式
MyBatis接口方法上可以接收各种各样的参数,MyBatis底层对于这些参数有不同的封装处理方式。我们以解读源码的形式对MyBatis提供的ParamNameResolver类进行参数封装解读。
单个参数:
1.POJO类型:(直接使用,属性名和参数占位符名称一致)
public class UserParam {
private String name;
private int age;
}
对应的 XML:
<select id="selectUserByPOJO" resultType="User">
SELECT * FROM users WHERE name = #{name} AND age = #{age}
</select>
2.Map集合:(直接使用,属性名和参数占位符名称一致)
Map<String, Object> params = new HashMap<>();
params.put("name", "John");
params.put("age", 30);
对应的 XML:
<select id="selectUserByMap" resultType="User">
SELECT * FROM users WHERE name = #{name} AND age = #{age}
</select>
3.Collection:
可以看出Collection会封装成Map集合,参数值会被封装成:
map.put("arg0", collection集合);
map.put("collection", collection集合);
4.List:也会被封装成map集合
如果是List,则会在Collection的基础上增加一个List键值。
map.put("arg0", List集合);
map.put("collection", List集合);
map.put("List", List集合);
5.Array:也会被封装成map集合
如果是Array数组,则会走另一个if语句。
map.put("arg0", 数组);
map.put("array",数组);
6.其他类型:直接使用
多个参数类型,
put出两个键值对,一个是arg0,另一个是param1。
map.put("arg0",参数值1)
map.put("param1",参数值1)
map.put("arg1",参数值2)
map.put("param2",参数值2)
User select(@Param("username") String username,String password);
注意:封装为Map集合,可以使用@param注解,替换Map集合中默认的arg键名。
-----------------@Param("username")
map.put("username",参数值1)
map.put("param1",参数值1)
map.put("arg1",参数值2)
map.put("param2",参数值2)
为什么会有arg和param两个键值对呢?
兼容不同的参数命名规则
arg0
,arg1
, ...:这种命名方式通常用于通过位置(索引)传递参数。在一些情况下,用户可能更喜欢或更习惯于通过参数的顺序来引用它们,而不是通过具体的参数名。这种方式在MyBatis的早期版本中较为常见,尤其是在使用XML映射文件时param1
,param2
, ...:这种命名方式则是基于参数的名称来传递参数。随着MyBatis的发展,基于名称的参数传递变得更加流行,因为它提供了更好的可读性和灵活性,尤其是在处理复杂对象或多个参数时。