MyBatis实现动态查询语句

MyBatis实现动态查询语句

一.为什么要使用动态查询语句?

废话,当然是为了代码的重用和简化操作接口,减少代码冗余。

二.什么情况下使用动态查询?

当页面中有多个查询类型相同但查询条件不同时,可以请求同一服务而带不同参数。

三.如何实现动态查询?

1.使用SQL类来动态生成SQL语句

由于@Select注解中不能进行逻辑判断,唯一能实现逻辑判断的只有java语言,故我们可以创建一个类来动态生成SQL语句,使用ibatis提供的SQL类可以创建SQL语句,具体如下:

package com.eshop.mapper.provider;
import com.mysql.jdbc.StringUtils;
import org.apache.ibatis.jdbc.SQL;
public class TypeSqlProvider {

    public String dynamicTypeSql(String type, String brands, String words){
        String sql=new SQL(){{
            SELECT(" *, spt.id spt_id , sb.id sb_id");
            FROM(" s_product sp ");
            LEFT_OUTER_JOIN(" s_product_type spt ON sp.product_type=spt.id  ");
            LEFT_OUTER_JOIN(" s_brand sb ON sp.product_brand=sb.id ");
            //jdbc驱动包中提供的一个字符串非空验证的方法
            if(!StringUtils.isNullOrEmpty(type)){
                WHERE(" sp.product_type=#{type} ");
            }
            if(!StringUtils.isNullOrEmpty(words)){
                //以下两种方式对应的是jdbc中的Statement和PreparedStatement
                //搜索历史模糊查询
                WHERE(" sp.product_name like '%${words}%'");
                //WHERE(" sp.product_name like \"%\"#{words}\"%\"");
            }
            if(!StringUtils.isNullOrEmpty(brands)){//brands中可能包含多个品牌id
                //分离品牌字符串
                String[] brandId_arr = brands.split(",");
                String sql_brands=" sb.id in (";
                for (int i = 0; i <brandId_arr.length ; i++) {
                    sql_brands+="'"+brandId_arr[i]+"'";
                    if(i<brandId_arr.length-1){
                        sql_brands+=",";
                    }
                }
                sql_brands+=")";
                WHERE(sql_brands);
            }
        }}.toString();
        return sql;
    }
}

只需要使用if来判断各个参数是否为空,不为空则WHERE生效,最后返回SQL的.toString()转换为String类型的SQL语句。

2.使用MyBatis的@SelectProvider注解

上述类实现后,我们就可以在mapper层中使用@SelectProvider注解来利用反射来创建对象并使用其中的动态语句生成方法,具体在mapper层代码如下;

  @SelectProvider(value = TypeSqlProvider.class,method="dynamicTypeSql")
    @ResultMap("pro_type_brand")
    List<Product> QueryProductsByParams(String type, String words, String brands);

其中参数value代表要使用的类类型,以创建实例,method就是我们要创建的实例要使用的方法,若查询返回字段名和实体属性名不同则需要手动映射,即使用Results和Result,由于我前面映射过,故在此直接使用@ResultMap注解调用前面的映射,然后我们就可以相继在Service层和Controller层中逐层调用。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值