版权声明:发扬开源精神,欢迎大家转载对自己有用的文章(●'◡'●) https://blog.csdn.net/jacksonary/article/details/83314552
1. 模糊查询
在查询时使用动态SQL,其中有一个需求是可以根据名字进行模糊匹配,我在映射文件mapper
是这么写的:
<select id="list" resultMap="BaseResultMap">
select 'false' as QUERYID,
<include refid="Base_Column_List"/>
from activity_award where 1=1
<if test="name!=null">
and name like %#{name}%
</if>
<if test="status!=null">
and status = #{status,jdbcType=TINYINT}
</if>
order by create_time desc
<if test="offset!=null and pageSize != null">
limit #{offset,jdbcType=INTEGER},
#{pageSize,jdbcType=INTEGER}
</if>
</select>
测试时出现SQL错误,如下:
### SQL: select 'false' as QUERYID, award_id, activity_id, name, limit_count, amount, price, completed_amount, status, create_time, update_time from activity_award where 1=1 and name like %?% order by create_time desc limit ?,?
### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '%'鼠标'% order by create_time desc' at line 9
可以发现在接口传过来的参数name=鼠标
传过来被转成了一个字符串%'鼠标'%
,而不是预期的%鼠标%
,想到SQL注入时$
和#
差异时,这种场景不需要它帮我作转换处理,是什么就是什么,不要加''
,料想此时选用${}
的方式就可以解决这个问题,将上述的%#{name}%
改成%${name}%
还是报错:
### SQL: select 'false' as QUERYID, award_id, activity_id, name, limit_count, amount, price, completed_amount, status, create_time, update_time from activity_award where 1=1 and name like %鼠标% order by create_time desc limit ?,?
### Cause: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '%鼠标% order by create_time desc' at line 9
发现%'鼠标'%
已经变成了%鼠标%
,
【解决】
- 使用
'%${name}%'
解决,但是${}
可能引发SQL注入的危险,不推荐使用; - 使用
"%"#{name}"%"
解决; - 使用MySQL中自带的
CONCAT(str1,str2,...)
函数进行字符串拼接(和java中的可变参数一个含义),改为concat('%', concat(#{name},'%'))
解决;
2. 关于resultMap
如果Mapper文件中需要多个返回值类型(这里只讨论返回对象类型,比如A和B两个对象),并且存在A对象的属性上加上几个属性后就是B对象,那在定义A的resultMap后,可以在定义B的resultMap时
继承A的resultMap,然后再添加几个额外属性即可,如:
<!-- 定义通用返回对象类型的 resultMap -->
<resultMap id="BaseResultMap" type="com.xx.common.dao.model.RfaPublic">
<result column="rfa_id" jdbcType="BIGINT" property="rfaId"/>
<result column="name" jdbcType="VARCHAR" property="name"/>
<result column="category_id" jdbcType="INTEGER" property="categoryId"/>
<result column="score" jdbcType="REAL" property="score"/>
<result column="level" jdbcType="TINYINT" property="level"/>
<result column="create_time" jdbcType="TIMESTAMP" property="createTime"/>
<result column="update_time" jdbcType="TIMESTAMP" property="updateTime"/>
</resultMap>
<!-- 定义DCBaseResultMap继承BaseResultMap -->
<resultMap id="DCBaseResultMap"type="com.xx.common.dao.model.DCRfaPublic" extends="BaseResultMap">
<result column="download_count" jdbcType="INTEGER" property="downloadCount"/>
<result column="owner" jdbcType="VARCHAR" property="owner"/>
<result column="is_mobile" jdbcType="TINYINT" property="isMobile"/>
</resultMap>
上述定义了两个resultMap
,BaseResultMap
拥有rfa_id
`update_time`7个字段,而`DCBaseResultMap`使用`extends`关键字继承了`BaseResultMap`,那此时`DCBaseResultMap`将拥有`rfa_id`update_time
7个字段,此外还有自己独有的download_count
~is_mobile
3个字段。