MyBatis 框架中动态SQL接受参数的处理方法

2021-10-27 0 By admin

MyBatis 框架中当使用 Mapper XML 文件编写具体SQL 语句时,会涉及到向动态SQL里传递参数的情况。其中包括单个参数、多个参数、对参数命名、POJO对象和Map类型等参数处理过程。

一、单个参数

#{arg}: 直接取出参数值;只有一个参数时可以随便写。

1.1、接口方法

User getOneParam(int id);

1.2、方法映射

<select id="getOneParam" resultType="org.hong.pojo.User">
  select * from user where id = #{user_id}
</select>

1.3、测试用例

@Test
public void testOneParam(){
  // 1.获取sqlSession对象
  SqlSession sqlSession = MyBatisUtil.getSqlSession();
  // 2.获取需要的mapper接口的代理对象
  UserMapper mapper = sqlSession.getMapper(UserMapper.class);
  // 3.调用对应的方法执行操作
  User oneParam = mapper.getOneParam(1);
  System.out.println(oneParam);
  // 4.提交事务
  sqlSession.commit();
  // 5.关闭sqlSession
  sqlSession.close();
}

二、多个参数

MyBatis 会多多个参数做特殊处理,多个参数会被封装成一个 map对象。

2.1、接口方法

User getParams(String name, String pwd);

2.2、方法映射

<select id="getParams" resultType="org.hong.pojo.User">
  <!-- 
    参数name可以使用 #{arg0} 或 #{param1} 取出
    参数pwd可以使用 #{arg1} 或 #{param2} 取出
   -->
  select * from user where name = #{arg0} and pwd = #{param2}
</select>

三、对参数命名

使用注解 @Param 指定参数的 key。

多个参数会被封装成一个map对象;使用 @param 注解给参数多加一个 key,原来的 arg 和 param 依旧能使用。

3.1、接口方法

User getAnnoParam(@Param("name") String name,String pwd);

3.2、方法映射

<select id="getAnnoParam" resultType="org.hong.pojo.User">
  select * from user where name = #{name} and pwd = #{param2}
</select>

四、POJO 对象

多个参数正好是业务逻辑的数据模型(实体类)的话,可以直接传入POJO对象。
通过 #{属性名} 的方式,可以取出传入的pojo对应属性的值。

4.1、接口方法

int updatePojo(User user);

4.2、方法映射

<update id="updatePojo">
  update user set name = #{name}, pwd = #{pwd} where id = #{id}
</update>

五、Map 类型

如果多个参数不是业务模型中的数据模型, 没有对应的POJO, 可以传入map 类型。
通过#{key}方法,可以取出map中key对应的值。

5.1、接口方法

User getMapParam(Map<string, object=""> map);</string,>

5.2、方法映射

<select id="getMapParam" resultType="org.hong.pojo.User">
  select * from user where name = #{name} and pwd = #{pwd}
</select>

5.3、测试用例

@Test
public void testMap(){
  // 1.获取sqlSession对象
  SqlSession sqlSession = MyBatisUtil.getSqlSession();
  // 2.获取需要的mapper接口的代理对象
  UserMapper mapper = sqlSession.getMapper(UserMapper.class);
  // 3.调用对应的方法执行操作
  Map<String, Object> map = new HashMap<>();
  map.put("name", "Tom");
  map.put("pwd", "123456");
  User mapParam = mapper.getMapParam(map);
  System.out.println(mapParam);
  // 4.提交事务
  sqlSession.commit();
  // 5.关闭sqlSession
  sqlSession.close();
}

六、补充:#{} 和 ${} 的区别和集合类型的参数

6.1、#{} 和 ${} 的区别

  1. #{}是占位符,是预编译处理。Mybatis 在处理#{}时,会将 sql 中的#{}替换为?号,调用 PreparedStatement 的set 方法来赋值。
  2. 使用#{}可以有效的防止 SQL 注入,提高系统安全性。
  3. ${}是拼接符,是字符串替换。Mybatis 在处理$ {}时,就是把${}替换成变量的值。

6.2、集合类型的参数

public User getEmpById(List<Integer> ids);
/*
如果是Collection(List, Set) or Array, 也会特殊处理, 把传入的list或数组封装在map中。
Key: Collection(collection) | List(list) | Array(array) | Set(set)
取值: 取出第一个id的值: #{list[0]}
*/

七、最终代码粘贴

7.1、Mapper 接口

package org.hong.mapper;
import org.apache.ibatis.annotations.Param;
import org.hong.pojo.User;
import java.util.Map;
public interface UserMapper {
  // 单个参数
  User getOneParam(int id);
  // 多个参数
  User getParams(String name, String pwd);
  // 命名参数
  User getAnnoParam(@Param("name") String name,String pwd);
  // pojo
  int updatePojo(User user);
  //map
  User getMapParam(Map<String, Object> map);
  // #{}和${}的区别
  List<User> getOrderBy(String order);
}

7.2、Mapper.xml 文件

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
    PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
    "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="org.hong.mapper.UserMapper">
  <!-- 单个参数 -->
  <select id="getOneParam" resultType="org.hong.pojo.User">
    select * from user where id = #{user_id}
  </select>
  <!-- 多个参数 -->
  <select id="getParams" resultType="org.hong.pojo.User">
    <!--
      参数name可以使用 #{0} 或 #{param1} 取出
      参数pwd可以使用 #{1} 或 #{param2} 取出
     -->
    select * from user where name = #{arg0} and pwd = #{param2}
  </select>
  <!-- 命名参数 -->
  <select id="getAnnoParam" resultType="org.hong.pojo.User">
    select * from user where name = #{name} and pwd = #{param2}
  </select>
  <!-- pojo -->
  <update id="updatePojo">
    update user set name = #{name}, pwd = #{pwd} where id = #{id}
  </update>
  <!-- map -->
  <select id="getMapParam" resultType="org.hong.pojo.User">
    select * from user where name = #{name} and pwd = #{pwd}
  </select>
 
  <!-- #{}和${}的区别 -->
  <select id="getOrderBy" resultType="org.hong.pojo.User">
    select * from user order by id ${order}
  </select>
</mapper>

7.3、测试用例

package org.hong.test;
import org.apache.ibatis.session.SqlSession;
import org.hong.mapper.UserMapper;
import org.hong.pojo.User;
import org.hong.util.MyBatisUtil;
import org.junit.Test;
import java.util.HashMap;
import java.util.Map;
public class CRUDTest {
  @Test
  public void testOneParam(){
    // 1.获取sqlSession对象
    SqlSession sqlSession = MyBatisUtil.getSqlSession();
    // 2.获取需要的mapper接口的代理对象
    UserMapper mapper = sqlSession.getMapper(UserMapper.class);
    // 3.调用对应的方法执行操作
    User oneParam = mapper.getOneParam(1);
    System.out.println(oneParam);
    // 4.提交事务
    sqlSession.commit();
    // 5.关闭sqlSession
    sqlSession.close();
  }
  @Test
  public void testParams(){
......
    // 3.调用对应的方法执行操作
    User oneParam = mapper.getParams("Tom", "123456");
    System.out.println(oneParam);
......
  }
  @Test
  public void testAnnoParam(){
......
    // 3.调用对应的方法执行操作
    User user = mapper.getAnnoParam("Tom", "123456");
    System.out.println(user);
......
  }

  @Test
  public void testUpdatePojo(){
......
    // 3.调用对应的方法执行操作
    User user = mapper.getOneParam(1);
    user.setPwd("654321");
    int i = mapper.updatePojo(user);
    System.out.println(i);
......
  }

  @Test
  public void testMap(){
......
    // 3.调用对应的方法执行操作
    Map<String, Object> map = new HashMap<>();
    map.put("name", "Tom");
    map.put("pwd", "123456");
    User mapParam = mapper.getMapParam(map);
    System.out.println(mapParam);
......
  }
  
  @Test
  public void test$(){
......
    // 3.调用对应的方法执行操作
    List<User> desc = mapper.getOrderBy("desc");
    desc.forEach(System.out :: println);
......
  }
}