MyBatis Order By 字符串替換
默認情況下,使用 #{} 參數語法時,MyBatis 會創建 PreparedStatement 參數占位符,並通過占位符安全地設置參數(就像使用 ? 一樣)。 這樣做更安全,更迅速,通常也是首選做法,不過有時你就是想直接在 SQL 語句中直接插入一個不轉義的字符串。 比如 ORDER BY 子句,這時候你可以:
ORDER BY ${columnName}
這樣,MyBatis 就不會修改或轉義該字符串了。
當 SQL 語句中的元數據(如表名或列名)是動態生成的時候,字符串替換將會非常有用。 舉個例子,如果你想 select 一個表任意一列的數據時,不需要這樣寫:
@Select("select * from user where id = #{id}")
User findById(@Param("id") long id);
@Select("select * from user where name = #{name}")
User findByName(@Param("name") String name);
@Select("select * from user where email = #{email}")
User findByEmail(@Param("email") String email);
// 其它的 "findByXxx" 方法
而是可以只寫這樣一個方法:
@Select("select * from user where ${column} = #{value}")
User findByColumn(@Param("column") String column, @Param("value") String value);
其中 ${column} 會被直接替換,而 #{value} 會使用 ? 預處理。 這樣,就能完成同樣的任務:
User userOfId1 = userMapper.findByColumn("id", 1L);
User userOfNameKid = userMapper.findByColumn("name", "kid");
User userOfEmail = userMapper.findByColumn("email", "noone@nowhere.com");
這種方式也同樣適用於替換表名的情況。
綜上所述,order by 進行排序可以這么寫:
@Select(select * from user order by ${value} desc)
List<User> findAll(@Param("column") String column);
xml寫法:
<select id="testGetOffers" resultType="com.xy.erp.saas.userserver.entity.Offer">
select * from offer o
where o.orderGUID = #{orderGUID}
<if test="word != null">
order by ${word} ${desc}
</if>
limit #{currIndex}, #{pageSize}
</select>
注意:用這種方式接受用戶的輸入,並用作語句參數是不安全的,會導致潛在的 SQL 注入攻擊。因此,要么不允許用戶輸入這些字段,要么自行轉義並檢驗這些參數。
