Mybatis sql 映射文件中, 可以通过#{} 或 KaTeX parse error: Expected 'EOF', got '#' at position 34: …参数. 通常情况下, 优先使用#̲{}, 对于#{} 不能解决的…{}.
1. ${} 与 #{} 的区别
- #{} 采用的是预编译sql, 使用的是JDBC的PrepareStatment, 可防止sql注入. 但是占位符只能在sql的where,set 之后出现.
- ${} 采用的是字符串替换, 直接将变量内容替换成字符串,拼接成sql, 可在sql的任何位置出现
- ${} 不支持位置参数, 只能通过@param 指定参数名称或直接从javaBean 中获取属性值.
1.1 sql 映射文件
编写sql文件时, 分别使用${} 和 #{} 各引用一个变量, 并观察Mybatis的日志输出.
<!-- 通过id 查询实体 -->
<select id="findById" resultType="UserPO">
select * from t_user_${createYear} where id = #{id}
</select>
1.2 mapper 方法签名
由于是多个参数, 所以需要采用命名方式传参.
UserPO findById(@Param("id") Integer id, @Param("createYear") String createYear);
1.3 测试
@Test
public void test_find(){
UserMapper userMapper = SqlSessionFactoryUtil.getMapper(UserMapper.class);
UserPO userPO = userMapper.findById(1, "2018");
System.out.println(userPO);
}
1.4 日志输出
从日志打印的sql拼接结果来看, ${createYear} 直接替换成了2018, 而#{id} 则是采用sql预编译的方式, 以占位符? 代替.
2019-05-27 15:20:57:411][main][DEBUG][o.z.l.m.l.mapper.UserMapper.findById]- ==> Preparing: select * from t_user_2018 where id = ?
[2019-05-27 15:20:57:450][main][DEBUG][o.z.l.m.l.mapper.UserMapper.findById]- ==> Parameters: 1(Integer)
[2019-05-27 15:20:57:476][main][DEBUG][o.z.l.m.l.mapper.UserMapper.findById]- <== Total: 1
2. ${} 的应用举例
由于#{}只能出现在sql语句中的where, set, values 等位置, 所以对于数据库分表, 动态排序等均无法很好的支持, 只能通过复杂的动态SQL方式来实现.
2.1 动态表名
<insert id="save" useGeneratedKeys="true" keyProperty="id">
insert into t_user_${createYear} values (null , #{username}, #{password}, #{createYear})
</insert>
2.2 动态排序
<select id="queryAll" resultType="UserPO">
select * from t_user_${createYear} order by id ${orderType}
</select>