Mybatis 模糊查询三种方法

背景

  由于项目需要模糊查询,所以需要使用 LIKE 子句。LIKE 子句需要使用 % 作为占位符,所以需要将 % 与字段值连接到一起。Mybatis 下大概有如下几种方式实现:①使用 $ 占位符,②使用数据库函数 concat ,③使用 Mybatis 的动态 sql 标签 ,下面会简单介绍下前两种的用法和缺陷,然后重点介绍第三种,如何使用以及存在的坑。

使用 $

  代码如下:

@Select({"<script>",
          " SELECT * FROM SSS WHERE STATUS=1 ",
           " <if test='keyWord != null'>",
           " AND `NAME` LIKE '%${keyWord}%'",
           " </if>",
           "<if test='roleId != null'>",
           " AND ROLE_ID = #{roleId} ",
           "</if>",
           "</script>"})
   List<SellerDo> querySellers(SellerQuery sellerQuery);

   弊端:使用 $ 作为占位符,会存在 sql 注入问题,生产环境中应当避免使用

使用数据库函数 concat

   concat 属于数据库函数,MySQL 和 Oracle 都支持,用于字符串连接,而且可以使用 # 作为占位符,防止 SQL 注入。
代码如下

@Select({"<script>",
           " SELECT * FROM SSS WHERE STATUS=1 ",
            " <if test='keyWord != null'>",
            " AND `NAME` LIKE concat('%', #{keyWord}, '%')",
            " </if>",
            "<if test='roleId != null'>",
            " AND ROLE_ID = #{roleId} ",
            "</if>",
            "</script>"})
    List<SellerDo> querySellers(SellerQuery sellerQuery);

  弊端:有些公司并不推荐使用数据库函数,因为可能会切换数据库,如果切换到一个不支持 concat 函数的数据库就尴尬了。

使用 Mybatis 的动态 sql 标签

  bind 元素可以从 OGNL 表达式中创建一个变量并将其绑定到上下文。使用 bind 标签就可以对某个字段进行’封装’,比如给上面的 keyWord 字段两端各加一个百分号,如下:

<bind name="keyWord",value="'%'+keyWord+'%'"/>

则模糊查询可以使用 优化一下:

@Select({ "<script>",
           " SELECT * FROM SSS WHERE STATUS=1 ",
            "<bind name='keyWord' value=\" '%' + keyWord + '%' \"/>",
            " <if test='keyWord != null'>",
                  " AND `NAME` LIKE #{keyWord}",
            "</if>",
            "<if test='roleId != null'>",
                  " AND ROLE_ID = #{roleId} ",
            "</if>",
            "</script>"})
    List<SellerDo> querySellers(SellerQuery sellerQuery);

  这种方式就比使用 $ 占位符安全,因为 # 占位符通过PreparedStatement预编译的,可以防止 SQL 注入,而且即使更换数据库也同样没有问题,这是目前最好的一种方式。

坑点

  场景:mapper 方法中只有一个参数且是对象类型时,可以不使用 @Param 注解声明变量,其它情况就必须使用 @Param 注解。在这里我还拿上文例子举例,即使 querySellers 方法只有一个变量且为 Java Bean 类型但是我同样可以使用@Param 修饰,代码如下:

@Select({ "<script>",
           " SELECT * FROM SSS WHERE STATUS=1 ",
            "<bind name='query.keyWord' value=\" '%' + query.keyWord + '%' \"/>",
            " <if test='query.keyWord != null'>",
                  " AND `NAME` LIKE #{query.keyWord}",
            "</if>",
            "<if test='query.roleId != null'>",
                  " AND ROLE_ID = #{query.roleId} ",
            "</if>",
            "</script>"})
    List<SellerDo> querySellers(@Param("query") SellerQuery sellerQuery);

  调用代码和测试代码:

  @Service
public class SellerServiceImpl implements SellerService {


    @Autowired
    private SellerDoMapper sellerDoMapper;

    @Override
    public void querySellers(SellerQuery sellerQuery) {
        sellerDoMapper.querySellers(sellerQuery)
                .forEach(System.out::println);
    }
}
---------------------------------------------------------------------
@SpringBootTest
public class SellerServiceTest {

    @Autowired
    private SellerService sellerService;

    @Test
    public void querySellers() {
        SellerQuery sellerQuery = new SellerQuery();
        sellerQuery.setKeyWord("nihao");
        // roleId 有值,注意
        sellerQuery.setRoleId(4L);
        sellerService.querySellers(sellerQuery);
    }
}

  执行测试代码,打印如下:
bind标签坑图

  这个问题困扰了我几个小时,原因下个专题再讨论,会涉及到 Mybatis 的底层,解决办法就是不加 @Param 注解,如果有多个参数,则放在一个对象当做参数,这是我目前的解法。
##后记
  本文介绍了使用 Mybatis 开发模糊查询的三种方法,分别介绍其用法以及弊端,大家可以按照自己的业务需求选择。读完点个赞吧。

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值