持续创作,加速成长!这是我参与「掘金日新计划 · 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 注入,提高系统安全性。
- Mybatis 会将 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、数据库的关键字,统一使用大写,例如:
SELECT、AS、FROM、WHERE。 - 2、每 5 个查询字段换一行,保持整齐。
- 3、
,的后面,和=的前后,需要有空格,更加清晰。 - 4、
SELECT、FROM、WHERE等,单独一行,高端大气。
方法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");
}
最后总结⭐️
建议分成两种情况进行处理:
- 实体类类型的参数
- 使用@Param标识参数