MyBatis使用过程中的注意点

版权声明:发扬开源精神,欢迎大家转载对自己有用的文章(●'◡'●) 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

发现%'鼠标'%已经变成了%鼠标%

【解决】

  1. 使用'%${name}%'解决,但是${}可能引发SQL注入的危险,不推荐使用;
  2. 使用"%"#{name}"%"解决;
  3. 使用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>

上述定义了两个resultMapBaseResultMap拥有rfa_id`update_time`7个字段,而`DCBaseResultMap`使用`extends`关键字继承了`BaseResultMap`,那此时`DCBaseResultMap`将拥有`rfa_id`update_time7个字段,此外还有自己独有的download_count~is_mobile3个字段。

猜你喜欢

转载自blog.csdn.net/jacksonary/article/details/83314552