注解方式配置MyBatis执行动态SQL

作者:梁开权,叩丁狼高级讲师。

各位小伙伴们大家好,逍遥又跟大家见面了,在上次分享中给大家分享了如何通过注解的方式来操作MyBatis,也都仅仅局限于静态SQL语句,这次给大家分享想如何通过注解的方式使用动态SQL

准备工作

事先建好表/domain/mapper/QueryObject

@Setter@Getter@ToString
public class Employee {
    private Long id; //代理主键
    private String name; //员工姓名
    private String age; //员工年龄
}

public interface EmployeeMapper {
    //查询符合条件的总行数
    Integer selectForCount(EmployeeQueryObject qo);
    //查询符合条件的对象
    List<?> selectForList(EmployeeQueryObject qo);
}

@Setter@Getter
public class EmployeeQueryObject {
    private int currentPage; //当前页
    private int pageSize; //页面容量

    private String name; //员工姓名的模糊查询
    private Integer minAge; //员工年龄的最小值范围查询
    private Integer maxAge; //员工年龄的最大值范围查询
     
    //取值前跳过的行数
    public int getStart() {
        return (currentPage - 1) * pageSize;
    }
}

方式1:

直接在mapper接口的方法中贴@Select注解在配置value属性,该属性中的SQL语句使用script标签包起来,表示里面使用了脚本语言

public interface EmployeeMapper {
    //查询符合条件的总行数
    @Select("<script>" +
            "select count(0) from employee" +
            "<where>" +
                "<if test='name != null'>" +
                    "and name like concat('%', #{name}, '%')"+
                "</if>"+
                "<if test='minAge != null'>" +
                    "and age >= #{minAge}"+
                "</if>"+
                "<if test='maxAge != null'>" +
                    "and age <= #{maxAge}"+
                "</if>"+
            "</where>" +
            "</script>")
    Integer selectForCount(EmployeeQueryObject qo);
    
    //查询符合条件的对象
    @Select("<script>" +
            "select id, name, age from employee" +
            "<where>" +
                "<if test='name != null'>" +
                    "and name like concat('%', #{name}, '%')"+
                "</if>"+
                "<if test='minAge != null'>" +
                    "and age >= #{minAge}"+
                "</if>"+
                "<if test='maxAge != null'>" +
                    "and age <= #{maxAge}"+
                "</if>"+
            "</where>" +
            "limit #{start}, #{pageSize}" +
            "</script>")
    List<?> selectForList(EmployeeQueryObject qo);
}

以上代码中存在了大量的重复代码,比如from语句和where的语句都是一样的,此时是这种直接注解中写SQL的方式是不能做抽取的,怎么办?我们可以使用另外的一种方式,把生成SQL语句的代码写在某个类的某个方法中,再告诉框架找某个类的某个方法拿到SQL语句即可

方式2:

自己定义一个类,在类中设计两个方法分别用于拿到selectForCount和selectForList的SQL语句,在此之前先介绍MyBatis的SQL对象,该对象用于生成最终的SQL语句


SQL对象

此时我们就可以通过自己动手创建SQL对象,从而拿到我们要的SQL语句

//员工对象的SQL提供者
public class EmployeeSQLProvider {
    //拿到查询总行数的SQL语句
    public String getCountSql(EmployeeQueryObject qo) {
        //创建SQL对象并设置select语句要查询的列
        SQL sql = new SQL().SELECT("count(0)"); 
        addFrom(sql); //添加from语句
        addWhere(sql, qo); //添加where语句
        return sql.toString();
    }

    //拿到查询集合对象的SQL语句
    public String getLimitSql(EmployeeQueryObject qo) {
        SQL sql = new SQL().SELECT("id, name, age");
        addFrom(sql);
        addWhere(sql, qo);
        return sql.toString();
    }

    //抽取拼接的from语句的方法
    private void addFrom(SQL sql) {
        sql.FROM("employee"); //往SQL对象中添加from语句
    }

    //抽取拼接的where语句的方法
    private void addWhere(SQL sql, EmployeeQueryObject qo) {
        //往SQL对象中动态的添加添加
        if (StringUtils.hasLength(qo.getName())) {
            sql.WHERE("e.name like #{name}");
        }
        if (qo.getMinAge() != null) {
            sql.WHERE("e.age >= #{minAge}");
        }
        if (qo.getMaxAge() != null) {
            sql.WHERE("e.age <= #{maxAge}");
        }
    }
}

有了上面的哪个SQL提供者,我们就可以告诉框架找EmployeeSQLProvider对象中的方法来拿到SQL语句,所以我们在mapper接口的方法中使用注解@SelectProvider,并且告诉该注解找EmployeeSQLProvider类中的哪个方法拿SQL语句即可,所以方式2就变成一下的样子

public interface EmployeeMapper {
    //type表示提供SQL的类,method表示该类中的哪个方法
    @SelectProvider(type= EmployeeSQLProvider.class, method="getCountSql")
    Integer selectForCount(EmployeeQueryObject qo);

    @SelectProvider(type= EmployeeSQLProvider.class, method="getLimitSql")
    List<?> selectForList(EmployeeQueryObject qo);
}

对比方式1大家应该不难发现方式2在配置上的简洁性,把复杂的逻辑操作拿到了代码中,同时也能抽取重复的代码,相对来讲方式2要更好些,大家学会了吗?本期就先分享到这来,我们下期再会

WechatIMG9.jpeg
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 1. 简介 1.1 什么是 MyBatis ? MyBatis 是支持定制化 SQL、存储过程以及高级映射的优秀的...
    笨鸟慢飞阅读 5,571评论 0 4
  • 1 Mybatis入门 1.1 单独使用jdbc编程问题总结 1.1.1 jdbc程序 上边使...
    哇哈哈E阅读 3,325评论 0 38
  • 相信很多女生,青春年少时,对另一半的择偶要求,都会说要找个灵魂伴侣 觉得这才是爱情的最高阶段,只有这样的爱情才是真...
    三十而丽阅读 690评论 2 8
  • 前陣子母親節剛過,又剛好我有好多的朋友跟同學已經當了年輕媽媽,我想分享一個小故事。 小時候我家有一台小小的錄放音...
    d21f5576b168阅读 354评论 0 1
  • ios11更新了。之前xcode9的bate版我也没时间看,知道今天要适配才发现问题来了。下午研究半天。感觉这玩意...
    xiaoliang1阅读 1,586评论 4 3