Mybatis中parameterType传入参数

CRUD标签都有一个属性parameterType,statement通过它指定接收的参数类型。
接收参数的方式有两种:

  1. #{}预编译
  2. ${}非预编译(直接的sql拼接,不能防止sql注入)

参数类型有三种:

  1. 基本数据类型
  2. HashMap(使用方式和pojo类似)
  3. Pojo自定义包装类型
1. ${}的用法

场景:数据库有两个一模一样的表。历史表,当前表
查询表中的信息,有时候从历史表中去查询数据,有时候需要去新的表去查询数据。希望使用1个方法来完成操作。
【示例】
第一步:添加一个接口
在UserMapper接口中,添加根据表名查询用户信息的方法:

/**
 * 通过用户名查询用户
 * @param tableName
 * @return
 */
List<User> queryUserListByTableName(String tableName);

第二步:编写一个查询的statement
在UserMapper映射文件中,添加方法对应的statement:

<!-- 通过表名查询数据 -->
<select id="queryUserListByTableName" resultType="User">
   select * from ${tableName}
</select>

第三步:编写测试方法

@Test
public void testQueryUserListByTableName(){
    List<User> list = userMapper.queryUserListByTableName("tb_user");
    System.out.println(list);
}

执行方法输出(报错):只能使用${value}来传递参数,其他任何字符串都不行
执行方法输出(报错)

如果你要动态传入的字段名是表名,并且sql执行是预编译的,这显然是不允许的,所以你必须改成非预编译的,也就是这样:
在一个参数的情况下必须,参数名称必须为value:即${value}

<!-- 通过表名查询数据 -->
<select id="queryUserListByTableName" resultType="User">
   select * from ${value}
</select>

注意:
使用 $ {} 去接收参数信息,在一个参数时,默认情况下必须使用${value}获取参数值

但是这并不是一种稳妥的解决方案,推荐使用@Param注解指定参数名.
接口修改如下:

/**
 * 通过用户名查询用户
 * @param tableName
 * @return
 */
List<User> queryUserListByTableName(@Param("tableName") String tableName);

映射文件修改如下:

<!-- 通过表名查询数据 -->
<select id="queryUserListByTableName" resultType="User">
   select * from ${tableName}
</select>
2. #{}的用法

#{}类似于sql语句中的?,但是单个参数和多个参数的使用方式稍微有点区别。

2.1 单个参数

参见之前的通过id查询数据的statement:

<select id="queryUserById" resultType="User">
       select * from tb_user where id = #{id}
   </select>

执行查询结果如下:#{}就相当于一个?,可以进行预编译的占位。
在这里插入图片描述
注意:在一个参数的情况下#{id}中的id可以修改成任意字符。
即使修改如下,也可以照常运行:

<select id="queryUserById" resultType="User">
       select * from tb_user where id = #{xxx}
</select>
2.2 多个参数

当mapper接口要传递多个参数时,有两种传递参数的方法:
1、 默认规则获取参数{arg0,arg1,param1,param2}
2、 使用@Param注解指定参数名

案例:实现一个简单的用户登录,根据username和password验证用户信息
在UserMapper接口中,添加登陆方法:

/**
 * 用户登陆
 * @param userName
 * @return
 */
User login(String userName,String password);

在UserMapper.xml配置中,添加登陆方法对应的Statement配置:

<select id="login" resultType="User">
   select * from tb_user where user_name = #{userName} and password = #{password}
</select>

在UserMapperTest测试用例中,添加测试方法:

@Test
public void testLogin(){
    User user = userMapper.login("zhangsan", "123456");
    System.out.println(user);
}

运行报错:
运行报错
注意报错信息:没有找到参数userName,可用的参数是:[arg0,arg1,param1,param2],所以可有以下解决方案:
解决方案一:
在映射文件里,通过#{arg0},#{arg1}获取参数

<select id="login" resultType="User">
   select * from tb_user where user_name = #{arg0} and password = #{arg1}
</select>

解决方案二:
在映射文件里,通过param1,param2获取参数

<!--
   通过参数的固定名称传递参数:param1,param2,param3依次类推
-->
<select id="login" resultType="User">
   select * from tb_user where user_name = #{param1} and password = #{param2}
</select>

最终解决方案:
在接口方法中的参数前,添加@Param注解指定参数名:

/**
 * 用户登陆
 * @param userName
 * @return
 */
User login(@Param("userName") String userName,@Param("password") String password);

映射文件中修改如下:

<!--
   通过参数的固定名称传递参数:param1,param2,param3依次类推
-->
<select id="login" resultType="User">
   select * from tb_user where user_name = #{userName} and password = #{password}
</select>

注意:
单个参数时,#{}与参数名无关的。
多个参数时,#{}和${}与参数名(@Param)有关。

什么时候需要加@Param注解?什么时候不加?
单个参数不加,多个参数加
终极解决方案:都加

3. HashMap参数

使用HashMap来传递参数
UserMapper接口方法:

   /**
     * 用户登陆,参数为map
     * @return
     */
    User loginMap(Map<String,String> map);

UserMapper配置文件:

<!--
   将map的key作为参数名称来传递参数
-->
<select id="loginMap" resultType="User">
   select * from tb_user where user_name = #{userName} and password = #{password}
</select>

测试用例:

@Test
public void testLoginMap(){
    Map<String, String> map = new HashMap<>();
    map.put("userName","zhangsan");
    map.put("password","123456");
    User user = userMapper.loginMap(map);
    System.out.println(user);
}
4. Pojo参数

使用pojo来传递参数
接口:

/**
 * 用户登陆,参数为pojo
 * @param user
 * @return
 */
User loginUser(User user);

映射文件:

<!--
   通过参数名称来调用User中的getter方法来获取参数
-->
<select id="loginUser" resultType="User">
   select * from tb_user where user_name = #{userName} and password = #{password}
</select>

测试:

@Test
public void testLoginUser(){
    User user = new User();
    user.setUserName("zhangsan");
    user.setPassword("123456");
    User queryUser = userMapper.loginUser(user);
    System.out.println(queryUser);
}
5. ※面试题(#、$区别)

在这里插入图片描述

5. #{}和${}的区别总结

#{}:
1、 是预编译
2、 编译成占位符
3、 可以防止sql注入
4、 自动判断数据类型
5、 一个参数时,可以使用任意参数名称进行接收

${}:
1、 非预编译
2、 sql的直接拼接
3、 不能防止sql注入
4、 需要判断数据类型,如果是字符串,需要手动添加引号。
5、 一个参数时,参数名称必须是value,才能接收参数。

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值