Mybatis中#和$的坑

最近在项目中遇到一个场景:依据不同的请求参数,将数据库的数据按不同的数据列进行排序提取。

Mapper文件截取如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
<select id="querySellGoodsOrderById" resultMap="BaseResultMap">
select id, title, description, like_count, view_count, upload_time
from goods
where status=0
<if test="idList!=null">
and id in
<foreach item="item" index="index" collection="idList"
open="(" separator="," close=")">
#{item}
</foreach>
</if>
order by #{order}
</select>

接口定义:

1
2
List<GoodsInfo> querySellGoodsOrderById(@Param("idList") List idList,
@Param("order") String order);

但是在测试中,代码参数order无论取’like_count’、’view_count’或’upload_time’方法执行结果都是保持同一种顺序。

其实,在Mybatis中#符号表示参数,如select * from test where value=#{param}传入参数param=”hello”后,实际生成select * from test where value='hello'。因此,在上面的场景中,实际的SQL结果是order by 'upload_time',而正确的结果应该是order by upload_time

在Mybatis还可以使用\$符号,\$表示原本的字符串,即传什么参数,SQL中就填入什么。如select * from test order by #{param}传入参数param=”time”后,实际生成select * from test order by time。这个才是上文场景中需要的。

注意点:

#号会使用PreparedStatement,变量处用?号代替,防止SQL注入,而\$号是直接替换没有这个功能。