尚硅谷MyBatis6_获得参数值的方式
MyBatis 获取参数值的两种方式:${}
和 #{}
-
${}
本质就是字符串拼接,使用字符串拼接的方式拼接 sql,若为字符串类型或日期类型的字段进行赋值时,需要手动加单引号
-
#{}
本质就是占位符赋值,使用占位符赋值的方式拼接 sql,此时为字符串类型或日期类型的字段进行赋值时,可以自动添加单引号。该方式可以避免 sql 注入
单个字面量类型的参数
若 mapper 接口中的方法参数为单个的字面量类型 此时可以使用 ${}
和 #{}
以任意的名称获取参数的值,注意 ${}
需要手动加单引号
使用 #{}
<!--User getUserByUsername(String username);-->
<select id="getUserByUsername" resultType="User">
select * from t_user where username = #{username}
</select>
事实上,#{}
里面写啥都行,比如写 #{aaa}
也是可以的,重点的是获取到值,但是建议还是写对应的名字,比较清楚
在底层中可以看到:
DEBUG 03-19 16:53:31,884 ==> Preparing: select * from t_user where username = ? (BaseJdbcLogger.java:135)
实际上也就是说采用了原生的占位符的方式
使用 ${}
<select id="getUserByUsername" resultType="User">
select * from t_user where username = '${username}'
</select>
注意使用 ${}
需要手动添加单引号,因为本质是字符串拼接
多个字面量类型的参数
若 mapper 接口中的方法参数为多个时,此时 MyBatis 会自动将这些参数放在一个 map 集合中,以 arg0,arg1...
为键,以参数为值;以 param1,param2...
为键,以参数为值;因此只需要通过 ${}
和 #{}
访问 map 集合的键就可以获取相对应的值,注意 ${}
需要手动加单引号
一个错误示范及解决方案
<!--User checkLogin(String username, String password);-->
<select id="checkLogin" resultType="User">
select * from t_user where username = #{username} and password = #{password}
</select>
Error querying database. Cause: org.apache.ibatis.binding.BindingException:
Parameter 'username' not found.
Available parameters are [arg1, arg0, param1, param2]
连 sql 语句都没有输出,说明解析 sql 语句出错了,应该通过 arg0、arg1 或者 param1、param2 获取
<!--User checkLogin(String username, String password);-->
<select id="checkLogin" resultType="User">
select * from t_user where username = #{arg0} and password = #{arg1}
-- 也可以这么写
-- select * from t_user where username = #{param1} and password = #{arg1}
</select>
arg 和 param 可以混着用,注意参数是第几个就行
map 集合类型的参数
若 mapper 接口中的方法需要的参数为多个时,此时可以手动创建 map 集合,将这些数据放在 map 中
只需要通过 ${}
和 #{}
访问 map 集合的键就可以获取相对应的值,注意 ${}
需要手动加单引号
<!--User checkLoginByMap(Map<String, Object> map);-->
<select id="checkLoginByMap" resultType="User">
select *
from t_user
where username = #{username}
and password = #{password}
</select>
@Test
public void testParamByMap() {
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
Map<String,Object> map = new HashMap<>();
map.put("username","admin");
map.put("password","123456");
User user = mapper.checkLoginByMap(map);
System.out.println(user);
}
相当于是 map 使用的是自定义的键名
实体类类型的参数
若 mapper 接口中的方法参数为实体类对象时
此时可以使用 ${}
和 #{}
,通过访问实体类对象中的属性名获取属性值,注意 ${}
需要手动加单引号
<!--int insertUserByEntity(User user);-->
<insert id="insertUserByEntity">
insert into t_user
values(null, #{username}, #{password}, #{age}, #{sex}, #{email})
</insert>
@Test
public void testInsertUser() {
SqlSession sqlSession = SqlSessionUtils.getSqlSession();
UserMapper mapper = sqlSession.getMapper(UserMapper.class);
User user = new User(null,"hello","123456",16,"男","1234@qq.com");
int result = mapper.insertUserByEntity(user);
System.out.println(result);
}
使用 @Param 标识参数
可以通过 @Param 注解标识 mapper 接口中的方法参数,此时,会将这些参数放在 map 集合中,以 @Param("属性值") 为键,以参数为值;以 param1,param2...
为键,以参数为值;只需要通过 ${}
和 #{}
访问 map 集合的键就可以获取相对应的值,注意 ${}
需要手动加单引号
使用 @Param 要注意,如果 #{}
内写的不是 @Param("")指定的属性名会报错:
意思是说要么用 param1 和 param2 这两个键;要么用 username 和 password 这两个键
<!--User checkLoginByParam(@Param("username") String username, @Param("password") String password);-->
<select id="checkLoginByParam" resultType="User">
select *
from t_user
where username = #{username}
and password = #{password}
</select>
注:建议要么传入实体类型,要么使用 @Param 注解