zoukankan      html  css  js  c++  java
  • Mybatis--Statement Builders

    SelectBuilder 的秘密

    SelectBuilder 类并不神奇, 如果你不了解它的工作机制也不会有什么好的作用。 别犹豫, 让我们来看看它是怎么工作的。 SelectBuilder 使用了静态引入和 TreadLocal 变量的组合来开 启简洁的语法可以很容易地用条件进行隔行扫描,而且为你保护所有 SQL 的格式。它允许 你创建这样的方法:

    public String selectBlogsSql() {
      BEGIN(); // Clears ThreadLocal variable
      SELECT("*");
      FROM("BLOG");
      return SQL();
    }

    这是一个非常简单的示例, 你也许会选择静态地来构建。 所以这里给出一个复杂一点的 示例:

    private String selectPersonSql() {
      BEGIN(); // Clears ThreadLocal variable
      SELECT("P.ID, P.USERNAME, P.PASSWORD, P.FULL_NAME");
      SELECT("P.LAST_NAME, P.CREATED_ON, P.UPDATED_ON");
      FROM("PERSON P");
      FROM("ACCOUNT A");
      INNER_JOIN("DEPARTMENT D on D.ID = P.DEPARTMENT_ID");
      INNER_JOIN("COMPANY C on D.COMPANY_ID = C.ID");
      WHERE("P.ID = A.ID");
      WHERE("P.FIRST_NAME like ?");
      OR();
      WHERE("P.LAST_NAME like ?");
      GROUP_BY("P.ID");
      HAVING("P.LAST_NAME like ?");
      OR();
      HAVING("P.FIRST_NAME like ?");
      ORDER_BY("P.ID");
      ORDER_BY("P.FULL_NAME");
      return SQL();
    }

    用字符串连接的方式来构建上面的 SQL 就会有一些繁琐了。比如:

    "SELECT P.ID, P.USERNAME, P.PASSWORD, P.FULL_NAME, "
    "P.LAST_NAME,P.CREATED_ON, P.UPDATED_ON " +
    "FROM PERSON P, ACCOUNT A " +
    "INNER JOIN DEPARTMENT D on D.ID = P.DEPARTMENT_ID " +
    "INNER JOIN COMPANY C on D.COMPANY_ID = C.ID " +
    "WHERE (P.ID = A.ID AND P.FIRST_NAME like ?) " +
    "OR (P.LAST_NAME like ?) " +
    "GROUP BY P.ID " +
    "HAVING (P.LAST_NAME like ?) " +
    "OR (P.FIRST_NAME like ?) " +
    "ORDER BY P.ID, P.FULL_NAME";

    如果你喜欢那样的语法,那么你就可以使用它。它很容易出错,要小心那些每行结尾增 加的空间。现在,即使你喜欢这样的语法,下面的示例比 Java 中的字符串连接要简单也是 没有疑问的:

    private String selectPersonLike(Person p){
      BEGIN(); // Clears ThreadLocal variable
      SELECT("P.ID, P.USERNAME, P.PASSWORD, P.FIRST_NAME, P.LAST_NAME");
      FROM("PERSON P");
      if (p.id != null) {
      WHERE("P.ID like #{id}");
      }
      if (p.firstName != null) {
      WHERE("P.FIRST_NAME like #{firstName}");
      }
      if (p.lastName != null) {
      WHERE("P.LAST_NAME like #{lastName}");
      }
      ORDER_BY("P.LAST_NAME");
      return SQL();
    }

    这个例子有什么特殊之处?如果你看得仔细,那就不同担心偶然会重复的“AND”关 键字,或在“WHERE”和“AND”或两者都没有中选择!上面的语句将会由例子对所有 PERSON 记录生成一个查询,有像参数一样的 ID 或 firstName 或 lastName-或这三者的任意 组合。SelectBuilder 对理解哪里放置“WHERE” ,哪里应该使用“AND”还有所有的字符串 连接都是很小心的。 最好的情况, 无论你以何种顺序调用这些方法 (只有一种例外使用 OR() 方法)。

    有两个方法会吸引你的眼球:BEGIN()和 SQL()。总之,每个 SelectBuilder 方法应该以 调用 BEGIN()开始,以调用 SQL()结束。当然你可以在中途提取方法来打断你执行的逻 辑,但是 SQL 生成的范围应该以 BEGIN()方法开始而且以 SQL()方法结束。BEGIN()方法清 理 ThreadLocal 变量,来确保你不会不小心执行了前面的状态,而且 SQL()方法会基于这些 调用, 从最后一次调用 BEGIN()开始组装你的 SQL 语句。 注意 BEGIN()有一个称为 RESET() 的代替方法,它们所做的工作相同,只是 RESET()会在特定上下文中读取的更好。

    要按照上面示例的方式使用 SelectBuilder,你应该静态引入如下内容:

    import static org.apache.ibatis.jdbc.SelectBuilder.*;

    只要这个被引入了, 那么你使用的类就会拥有 SelectBuilder 的所有可用的方法。 下表就 是可用方法的完整列表:

    方法

    描述

    BEGIN() / RESET() 这些方法清理 SelectBuilder 类的 ThreadLocal 的状态,而且 准备构建新的语句。当开始一条新的语句时,BEGIN()读取 得最好。当在执行中间因为某些原因(在某些条件下,也许 处理逻辑需要一个完整的而且不同的语句)要清理一条语句 时 RESET()读取的做好。
    SELECT(String) 开始或附加一个 SELECT 子句。可以被多次调用,而且参数 会被追加在 SELECT 子句后面。 参数通常是逗号分隔的列名 列表和别名,但要是驱动程序可以接受的东西。
    SELECT_DISTINCT(String) 开始或附加一个 SELECT 子句, 也在生成的查询语句中添加 “DISTINCT”关键字。可以被多次调用,而且参数会被追 加在 SELECT 子句后面。 参数通常是逗号分隔的列名列表和 别名,但要是驱动程序可以接受的东西。
    FROM(String) 开始或附加一个 FROM 子句。 可以被多次调用, 而且参数会 被追加在 FROM 子句后面。 参数通常是表明或别名, 或是驱 动程序可以接受的任意内容。
    • JOIN(String)
    • INNER_JOIN(String)
    • LEFT_OUTER_JOIN(String)
    • RIGHT_OUTER_JOIN(String)
    基于调用的方法,添加一个合适类型的新的 JOIN 子句。参 数可以包含列之间基本的 join 连接还有条件连接。
    WHERE(String) 添加一个新的 WHERE 条件子句,由 AND 串联起来。可以 被多次调用, AND 告诉它来串联一个新的条件。 由 使用 OR() 方法来分隔 OR 条件。
    OR() 使用 OR 来分隔当前 WHERE 子句的条件。 可以被多次调用, 但是在一行上多次调用会生成不稳定的 SQL。
    AND() 使用 AND 来分隔当前 WHERE 字句的条件。可以被多次调 用,但是在一行上多次调用会生成不稳定的 SQL。因为 WHERE 和 HAVING 两者都自动串联 AND,这样使用是非 常罕见的,包含它也仅仅是为了完整性。
    GROUP_BY(String) 附加一个新的 GROUP BY 子句,由逗号串联起来。可以被 多次调用,每次使用逗号来告诉它串联一个新的条件。
    HAVING(String) 附加一个新的 HAVING 条件子句,由 AND 串联起来。可以 被多次调用,每次使用 AND 来告诉它要串联新的条件。使 用 OR()方法来分隔 OR 条件。
    ORDER_BY(String) 附加一个新的 ORDER BY 子句,由逗号串联起来。可以被 多次调用,每次使用逗号来告诉它串联新的条件。
    SQL() 这会返回生成 SQL 而且重置 SelectBuilder 的状态(正如 BEGIN()或 RESET()方法被调用)。因此,这个方法只能被调 用一次!

    SqlBuilder

    和 SelectBuilder 相似,MyBatis 也包含一个一般性的 SqlBuilder。它包含 SelectBuilder 的所有方法,还有构建 insert,update 和 delete 的方法。在 DeleteProvider,InsertProvider 或 UpdateProvider 中(还有 SelectProvider)构建 SQL 字符串时这个类就很有用。

    在上述示例中要使用 SqlBuilder,你只需简单静态引入如下内容:

    import static org.apache.ibatis.jdbc.SqlBuilder.*;

    SqlBuilder 包含 SelectBuilder 中的所有方法,还有下面这些额外的方法:

    方法 描述
    DELETE_FROM(String) 开始一个 delete 语句,要指定删除的表。通常它后面要跟着一个 WHERE 语句!
    INSERT_INTO(String) 开始一个 insert 语句, 要指定插入的表。 它的后面要跟着一个或多 个 VALUES()调用。
    SET(String) 为更新语句附加“set”内容的列表。
    UPDATE(String) 开始一个 update 语句,要指定更新的表。它的后面要跟着一个或 多个 SET()调用,通常需要一个 WHERE()调用。
    VALUES(String, String) 附加到 insert 语句后。 第一个参数是要插入的列名, 第二个参数是 要插入的值。

    这里是一些示例:

    public String deletePersonSql() {
      BEGIN(); // Clears ThreadLocal variable
      DELETE_FROM("PERSON");
      WHERE("ID = ${id}");
      return SQL();
    }
    
    public String insertPersonSql() {
      BEGIN(); // Clears ThreadLocal variable
      INSERT_INTO("PERSON");
      VALUES("ID, FIRST_NAME", "${id}, ${firstName}");
      VALUES("LAST_NAME", "${lastName}");
      return SQL();
    }
    
    public String updatePersonSql() {
      BEGIN(); // Clears ThreadLocal variable
      UPDATE("PERSON");
      SET("FIRST_NAME = ${firstName}");
      WHERE("ID = ${id}");
      return SQL();
    }
    









  • 相关阅读:
    C#/JAVA 程序员转GO/GOLANG程序员笔记大全(DAY 04)
    C#/JAVA 程序员转GO/GOLANG程序员笔记大全(DAY 03)
    C#/JAVA 程序员转GO/GOLANG程序员笔记大全(DAY 02)
    C#/Java 程序员转GO/golang程序员笔记大全(day 01)
    selenium grid配置
    JUnit和TestNG的区别
    【转载】 HttpClient、HttpURLConnection、OKHttp和Volley优缺点和性能对比
    selenide总结
    docker操作
    python连接oracle数据库
  • 原文地址:https://www.cnblogs.com/archermeng/p/7537357.html
Copyright © 2011-2022 走看看