MyBatis获取参数值

112 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第13天,点击查看活动详情


4 MyBatis获取参数值(重点)

4.1 #{} 和 ${} 的区别是什么?

  • ${}:本质就是字符串替换。

    • 可以用于 XML 标签属性值
    • 可以用于SQL 内部(不推荐,有sql注入风险)
 <dataSource type="UNPOOLED">
     <property name="driver" value="${driver}"/>
     <property name="url" value="${url}"/>
     <property name="username" value="${username}"/>
 </dataSource>
 ​
 <select id="getSubject3" parameterType="Integer" resultType="Subject">
     SELECT * FROM subject
     WHERE id = ${id}
 </select>
  • #{}:本质就是sql的参数占位符

    • Mybatis 会将 SQL 中的 #{} 替换为 ?
    • 在 SQL 执行前会使用 PreparedStatement 的参数设置方法,按序给 SQL 的 ? 号占位符设置参数值,比如 ps.setInt(0, parameterValue) 。 所以,#{}预编译处理,可以有效防止 SQL 注入,提高系统安全性。

4.2 单个字面量类型的方法参数

可以使用{}和#{}以任意的名称(最好见名识意)获取参数的值,注意{}需要手动加单引号

 <!--User getUserByUsername(String username);-->
 <select id="getUserByUsername" resultType="User">
   select * from t_user where username = #{username}
 </select>
 <!--User getUserByUsername(String username);-->
 <select id="getUserByUsername" resultType="User">  
   select * from t_user where username = '${username}'  
 </select>

4.3 多个字面量类型的方法参数

若mapper接口中的方法参数为多个时,MyBatis会自动将这些参数放在一个map集合中

 1. 以arg0,arg1...为键,以参数为值;
 2. 以param1,param2...为键,以参数为值;

因此只需要通过{}和#{}访问map集合的键就可以获取相对应的值,注意{}需要手动加单引号。

使用arg或者param都行,要注意的是,arg是从arg0开始的,param是从param1开始的

 <!--User checkLogin(String username,String password);-->
 <select id="checkLogin" resultType="User">  
   select * from t_user where username = #{arg0} and password = #{arg1}  
 </select>
 <!--User checkLogin(String username,String password);-->
 <select id="checkLogin" resultType="User">
   select * from t_user where username = '${param1}' and password = '${param2}'
 </select>

4.4 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 checkLoginByMap() {
   SqlSession sqlSession = SqlSessionUtils.getSqlSession();
   ParameterMapper mapper = sqlSession.getMapper(ParameterMapper.class);
   
   Map<String,Object> map = new HashMap<>();
   map.put("usermane","admin");
   map.put("password","123456");
   
   User user = mapper.checkLoginByMap(map);
   System.out.println(user);
 }

4.5 实体类对象类型的方法参数

可以使用{}和#{},**通过访问实体类对象中的属性名获取属性值**,注意{}需要手动加单引号

 <!--int insertUser(User user);-->
 <insert id="insertUser">
   insert into t_user values(null,#{username},#{password},#{age},#{sex},#{email})
 </insert>
 @Test
 public void insertUser() {
   SqlSession sqlSession = SqlSessionUtils.getSqlSession();
   ParameterMapper mapper = sqlSession.getMapper(ParameterMapper.class);
   
   User user = new User(null,"Tom","123456",12,"男","123@321.com");
   mapper.insertUser(user);
 }

当实体类中的属性名和表中的字段名不一样 ,怎么办?

方法1:在查询的 SQL 语句中定义字段名的别名,让字段名的别名和实体类的属性名一致。

 <select id="selectOrder" parameterType="Integer" resultType="Order"> 
     SELECT order_id AS id, order_no AS orderno, order_price AS price 
     FROM orders 
     WHERE order_id = #{id}
 </select>

建议:

  • 1、数据库的关键字,统一使用大写,例如:SELECTASFROMWHERE
  • 2、每 5 个查询字段换一行,保持整齐。
  • 3、, 的后面,和 = 的前后,需要有空格,更加清晰。
  • 4、SELECTFROMWHERE 等,单独一行,高端大气。

方法2:通过配置实现自动的下划线转驼峰

大多数场景下,数据库字段名和实体类中的属性名差,主要是前者为下划线风格,后者为驼峰风格。在这种情况下,可以直接配置如下,实现自动的下划线转驼峰的功能。

 <setting name="logImpl" value="LOG4J"/>
     <setting name="mapUnderscoreToCamelCase" value="true" />
 </settings>

也就说,约定大于配置。非常推荐!

方法3:通过 <resultMap> 来映射字段名和实体类属性名的一一对应的关系。

 <resultMap type="me.gacl.domain.Order" id=”OrderResultMap”> 
     <!- 用 id 属性来映射主键字段 -> 
     <id property="id" column="order_id"> 
     <!-result 属性来映射非主键字段,property 为实体类属性名,column 为数据表中的属性 -> 
     <result property="orderNo" column ="order_no" /> 
     <result property="price" column="order_price" /> 
 </resultMap>
 ​
 <select id="getOrder" parameterType="Integer" resultMap="OrderResultMap">
     SELECT * 
     FROM orders 
     WHERE order_id = #{id}
 </select>
  • 此处 SELECT * 仅仅作为示例只用,实际场景下,千万千万千万不要这么干。用多少字段,查询多少字段。
  • 相比第一种,第三种的重用性会好一些。

4.6 使用@Param注解标识参数

可以通过@Param注解标识mapper接口中的方法参数,此时会将这些参数放在map集合中。

 1. 以@Param注解的value属性值为键,以参数为值;
 2. 以param1,param2...为键,以参数为值;

只需要通过{}和#{}访问map集合的键就可以获取相对应的值,注意{}需要手动加单引号

 接口中
 <!--User CheckLoginByParam(@Param("username") String username, @Param("password") String password);-->
 ​
 xml中
 <select id="CheckLoginByParam" resultType="User">
   select * from t_user where username = #{username} and password = #{password}
 </select>
 @Test
 public void checkLoginByParam() {
   SqlSession sqlSession = SqlSessionUtils.getSqlSession();
   ParameterMapper mapper = sqlSession.getMapper(ParameterMapper.class);
   
   mapper.CheckLoginByParam("admin","123456");
 }

最后总结⭐️

建议分成两种情况进行处理:

  1. 实体类类型的参数
  2. 使用@Param标识参数