开发中常用的Mybatis使用总结

16 篇文章 0 订阅

mybatis使用总结

介绍
首个类持久性框架
分为JDBC(原始SQL)和Hibernate(ORM)简化绝大部分JDBC代码,
手工设置参数和获取结果
灵活,使用者能够完全控制SQL,支持高级映射

防止sql注入

说明:在MyBatis中,使用XML文件或注释来进行配置和映射,将接口和Java POJO(普通的旧Java对象)映射到数据库记录

xml例子
映射器界面

@Mapper
public interface UserMapper {
    User getById(int id);
}

** XML配置文件**

<select id="getById" resultType="org.example.User">
 SELECT * FROM user WHERE id = #{id}
</select

注释示例

@Mapper
public interface UserMapper {
    @Select("SELECT * FROM user WHERE id= #{id}")
    User getById(@Param("id") int id);
}

可以看到,使用者需要自己编写SQL语句,因此当使用不当时,会导致注入问题

与使用JDBC不同的是,MyBatis使用#{}和${}来进行参数值替换

使用#{}语法时,MyBatis会自动生成PreparedStatement,使用参数绑定(?)的方式来设置值,
上述两个示例等价的JDBC查询代码如下:

String sql = "SELECT * FROM users WHERE id = ?";
PreparedStatement ps = connection.prepareStatement(sql);
ps.setInt(1, id);

因此#{}可以有效防止SQL注入,详细可参考http://www.mybatis.org/mybatis-3/sqlmap-xml.html 字符串替换部分

而使用${}语法时,MyBatis会直接注入原始字符串,即相当于分段字符串,因此会导致SQL注入,如

<select id="getByName" resultType="org.example.User">
 SELECT * FROM user WHERE name = '${name}' limit 1
</select>

名称估计’ or ‘1’='1,实际执行的语句为

SELECT * FROM user WHERE name = '' or '1'='1' limit 1

因此建议尽量使用#{},但有些时候,如按语句排序,使用#{}会导致错误,如

ORDER BY #{sortBy}

sortBy参数估计name,替换后会成为

ORDER BY "name"

即以字符串“ name”来排序,而不是按名称排序,详细可参考https://stackoverflow.com/a/32996866/6467552。

这种情况就需要使用 ${}

ORDER BY ${sortBy}

使用了${}后,使用者需要自行过滤输入,方法有:

代码层使用白名单的方式,限制sortBy允许的值,如只能为name,email变量,异常情况则设置为替换值name

在XML配置文件中,使用if标签来进行判断

Mapper接口方法

List<User> getUserListSortBy(@Param("sortBy") String sortBy);
<select id="getUserListSortBy" resultType="org.example.User">
  SELECT * FROM user
  <if test="sortBy == 'name' or sortBy == 'email'">
 order by ${sortBy}
  </if>
</select>

因为Mybatis不支持else,需要替换值的情况,可以使用 choose (when, otherwise)

<select id="getUserListSortBy" resultType="org.example.User">
  SELECT * FROM user
  <choose>
    <when test="sortBy == 'name' or sortBy == 'email'">
      order by ${sortBy}
    </when>
    <otherwise>
      order by name
    </otherwise>
 </choose>
</select>

like语句

在代码层,在参数值两边加上%,然后再使用#{}

使用bind标签来构造新参数,然后再使用#{}

Mapper接口方法

List<User> getUserListLike(@Param("name") String name);

xml配置文件

<select id="getUserListLike" resultType="org.example.User">
    <bind name="pattern" value="'%' + name + '%'" />
    SELECT * FROM user
    WHERE name LIKE #{pattern}
</select>

语句内部的值为OGNL表达式,具体可参考http://www.mybatis.org/mybatis-3/dynamic-sql.html bind部分

使用SQL concat()函数

<select id="getUserListLikeConcat" resultType="org.example.User">
 SELECT * FROM user WHERE name LIKE concat ('%', #{name}, '%')
</select>

除了注入问题之外,这里还需要对用户的输入进行过滤,永久有通配符,
否则在表中数据量中断的时候,假设用户输入为%%,会进行全表模糊查询,
严重情况下可导致DOS ,参考http://www.tothenew.com/blog/sql-wildcards-is-your-application-safe/

IN条件

使用和#{}

Mapper接口方法

List<User> getUserListIn(@Param("nameList") List<String> nameList);
<select id="selectUserIn" resultType="com.example.User">
  SELECT * FROM user WHERE name in
  <foreach item="name" collection="nameList"
           open="(" separator="," close=")">
        #{name}
  </foreach>
</select>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

意田天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值