学习笔记,选自Mybatis官方中文文档:http://www.mybatis.org/mybatis-3/zh/statement-builders.html

问题

  Java程序员面对的最痛苦的事情之一就是在Java代码中嵌入SQL语句。这么来做通常是由于SQL语句需要动态来生成-否则可以将它们放到外部文件或者存储过程中。正如你已经看到的那样,MyBatis在它的XML映射特性中有一个强大的动态SQL生成方案。但有时在Java代码内部创建SQL语句也是必要的。此时,MyBatis有另外一个特性可以帮到你,在减少典型的加号,引号,新行,格式化问题和嵌入条件来处理多余的逗号或 AND 连接词之前。事实上,在Java代码中来动态生成SQL代码就是一场噩梦。例如:

String 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";

The Solution

  MyBatis 3提供了方便的工具类来帮助解决该问题。使用SQL类,简单地创建一个实例来调用方法生成SQL语句。上面示例中的问题就像重写SQL类那样:

private String selectPersonSql() {
  return new SQL() {{
    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");
  }}.toString();
}

  该例中有什么特殊之处?当你仔细看时,那不用担心偶然间重复出现的"AND"关键字,或者在"WHERE"和"AND"之间的选择,抑或什么都不选。该SQL类非常注意"WHERE"应该出现在何处,哪里又应该使用"AND",还有所有的字符串链接。

SQL类

 // Anonymous inner class
 public String deletePersonSql() {
   return new SQL() {{
     DELETE_FROM("PERSON");
     WHERE("ID = #{id}");
   }}.toString();
 }

 // Builder / Fluent style
 public String insertPersonSql() {
   String sql = new SQL()
     .INSERT_INTO("PERSON")
     .VALUES("ID, FIRST_NAME", "#{id}, #{firstName}")
     .VALUES("LAST_NAME", "#{lastName}")
     .toString();
   return sql;
 }

 // With conditionals (note the final parameters, required for the anonymous inner class to access them)
 public String selectPersonLike(final String id, final String firstName, final String lastName) {
   return new SQL() {{
     SELECT("P.ID, P.USERNAME, P.PASSWORD, P.FIRST_NAME, P.LAST_NAME");
     FROM("PERSON P");
     if (id != null) {
       WHERE("P.ID like #{id}");
     }
     if (firstName != null) {
       WHERE("P.FIRST_NAME like #{firstName}");
     }
     if (lastName != null) {
       WHERE("P.LAST_NAME like #{lastName}");
     }
     ORDER_BY("P.LAST_NAME");
   }}.toString();
 }

 public String deletePersonSql() {
   return new SQL() {{
     DELETE_FROM("PERSON");
     WHERE("ID = #{id}");
   }}.toString();
 }

 public String insertPersonSql() {
   return new SQL() {{
     INSERT_INTO("PERSON");
     VALUES("ID, FIRST_NAME", "#{id}, #{firstName}");
     VALUES("LAST_NAME", "#{lastName}");
   }}.toString();
 }

 public String updatePersonSql() {
   return new SQL() {{
     UPDATE("PERSON");
     SET("FIRST_NAME = #{firstName}");
     WHERE("ID = #{id}");
   }}.toString();
 }
方法 描述
  • SELECT(String)
  • SELECT(String...)
开始或插入到 SELECT子句。 可以被多次调用,参数也会添加到 SELECT子句。 参数通常使用逗号分隔的列名和别名列表,但也可以是数据库驱动程序接受的任意类型。
  • SELECT_DISTINCT(String)
  • SELECT_DISTINCT(String...)
开始或插入到 SELECT子句, 也可以插入 DISTINCT关键字到生成的查询语句中。 可以被多次调用,参数也会添加到 SELECT子句。 参数通常使用逗号分隔的列名和别名列表,但也可以是数据库驱动程序接受的任意类型。
  • FROM(String)
  • FROM(String...)
开始或插入到 FROM子句。 可以被多次调用,参数也会添加到 FROM子句。 参数通常是表名或别名,也可以是数据库驱动程序接受的任意类型。
  • JOIN(String)
  • JOIN(String...)
  • INNER_JOIN(String)
  • INNER_JOIN(String...)
  • LEFT_OUTER_JOIN(String)
  • LEFT_OUTER_JOIN(String...)
  • RIGHT_OUTER_JOIN(String)
  • RIGHT_OUTER_JOIN(String...)
基于调用的方法,添加新的合适类型的 JOIN子句。 参数可以包含由列命和join on条件组合成标准的join。
  • WHERE(String)
  • WHERE(String...)
插入新的 WHERE子句条件, 由AND链接。可以多次被调用,每次都由AND来链接新条件。使用 OR() 来分隔OR
OR() 使用OR来分隔当前的 WHERE子句条件。 可以被多次调用,但在一行中多次调用或生成不稳定的SQL
AND() 使用AND来分隔当前的 WHERE子句条件。 可以被多次调用,但在一行中多次调用或生成不稳定的SQL。因为 WHEREHAVING 二者都会自动链接 AND, 这是非常罕见的方法,只是为了完整性才被使用。
  • GROUP_BY(String)
  • GROUP_BY(String...)
插入新的 GROUP BY子句元素,由逗号连接。 可以被多次调用,每次都由逗号连接新的条件。
  • HAVING(String)
  • HAVING(String...)
插入新的 HAVING子句条件。 由AND连接。可以被多次调用,每次都由AND来连接新的条件。使用 OR() 来分隔OR.
  • ORDER_BY(String)
  • ORDER_BY(String...)
插入新的 ORDER BY子句元素, 由逗号连接。可以多次被调用,每次由逗号连接新的条件。
DELETE_FROM(String) 开始一个delete语句并指定需要从哪个表删除的表名。通常它后面都会跟着WHERE语句!
INSERT_INTO(String) 开始一个insert语句并指定需要插入数据的表名。后面都会跟着一个或者多个VALUES() or INTO_COLUMNS() and INTO_VALUES()。
  • SET(String)
  • SET(String...)
针对update语句,插入到"set"列表中
UPDATE(String) 开始一个update语句并指定需要更新的表明。后面都会跟着一个或者多个SET(),通常也会有一个WHERE()。
VALUES(String, String) 插入到insert语句中。第一个参数是要插入的列名,第二个参数则是该列的值。
INTO_COLUMNS(String...) Appends columns phrase to an insert statement. This should be call INTO_VALUES() with together.
INTO_VALUES(String...) Appends values phrase to an insert statement. This should be call INTO_COLUMNS() with together.

  Since version 3.4.2, you can use variable-length arguments as follows:

 public String selectPersonSql() {
   return new SQL()
     .SELECT("P.ID", "A.USERNAME", "A.PASSWORD", "P.FULL_NAME", "D.DEPARTMENT_NAME", "C.COMPANY_NAME")
     .FROM("PERSON P", "ACCOUNT A")
     .INNER_JOIN("DEPARTMENT D on D.ID = P.DEPARTMENT_ID", "COMPANY C on D.COMPANY_ID = C.ID")
     .WHERE("P.ID = A.ID", "P.FULL_NAME like #{name}")
     .ORDER_BY("P.ID", "P.FULL_NAME")
     .toString();
 }

 public String insertPersonSql() {
   return new SQL()
     .INSERT_INTO("PERSON")
     .INTO_COLUMNS("ID", "FULL_NAME")
     .INTO_VALUES("#{id}", "#{fullName}")
     .toString();
 }

 public String updatePersonSql() {
   return new SQL()
     .UPDATE("PERSON")
     .SET("FULL_NAME = #{fullName}", "DATE_OF_BIRTH = #{dateOfBirth}")
     .WHERE("ID = #{id}")
     .toString();
 }

Mybatis学习--Sql语句构建器的更多相关文章

  1. Java-MyBatis:MyBatis 3 | SQL 语句构建器类

    ylbtech-Java-MyBatis:MyBatis 3 | SQL 语句构建器类 1.返回顶部 1. SQL语句构建器类 问题 Java程序员面对的最痛苦的事情之一就是在Java代码中嵌入SQL ...

  2. mybatis之Sql语句构建器

    SQL类: 方法 描述 SELECT(String) SELECT(String...) 开始或插入到 SELECT子句. 可以被多次调用,参数也会添加到 SELECT子句. 参数通常使用逗号分隔的列 ...

  3. Java数据持久层框架 MyBatis之API学习九(SQL语句构建器详解)

    对于MyBatis的学习而言,最好去MyBatis的官方文档:http://www.mybatis.org/mybatis-3/zh/index.html 对于语言的学习而言,马上上手去编程,多多练习 ...

  4. Mybatis——SQL语句构建器类

    SQL语句构建器类 问题 Java程序员面对的最痛苦的事情之一就是在Java代码中嵌入SQL语句.这么来做通常是由于SQL语句需要动态来生成-否则可以将它们放到外部文件或者存储过程中.正如你已经看到的 ...

  5. SQL语句构建器类

    问题 Java程序员面对的最痛苦的事情之一就是在Java代码中嵌入SQL语句.这么来做通常是由于SQL语句需要动态来生成-否则可以将它们放到外部文件或者存储过程中.正如你已经看到的那样,MyBatis ...

  6. 《Mybatis 手撸专栏》第9章:细化XML语句构建器,完善静态SQL解析

    作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 你只是在解释过程,而他是在阐述高度! 如果不是长时间的沉淀.积累和储备,我一定也没有 ...

  7. mybatis实战教程(mybatis in action)之八:mybatis 动态sql语句

    mybatis 的动态sql语句是基于OGNL表达式的.可以方便的在 sql 语句中实现某些逻辑. 总体说来mybatis 动态SQL 语句主要有以下几类:1. if 语句 (简单的条件判断)2. c ...

  8. springmvc 项目完整示例04 整合mybatis mybatis所需要的jar包 mybatis配置文件 sql语句 mybatis应用

    百度百科: MyBatis 本是apache的一个开源项目iBatis, 2010年这个项目由apache software foundation 迁移到了google code,并且改名为MyBat ...

  9. Mybatis 动态Sql语句《常用》

    MyBatis 的强大特性之一便是它的动态 SQL.如果你有使用 JDBC 或其他类似框架的经验,你就能体会到根据不同条件拼接 SQL 语句有多么痛苦.拼接的时候要确保不能忘了必要的空格,还要注意省掉 ...

随机推荐

  1. 浅析js绑定同一个事件依次触发问题系列(一)

    算了 还是上代码吧  记得写过这篇文章,但是找不到了(对,就是找不到了,算了再写一遍吧) 也是在群中有人问这个绑定不同事件 或者同一个事件的依次触发问题 个人建议如果是一个事件的话那么最好写成函数, ...

  2. Struts中类型转换踩的坑

    出现的异常: 当我输入的数据很大时候,转换后如上,这并不是我想要的, 出现问题的原因: Struts2对常用的数据类型如String.Integer.Double等都添加了转换器进行对应的转换操作. ...

  3. 三款查看class文件结构的工具

    classpy JavaClassViewer jclasslib

  4. python三大器

    装饰器 装饰器的作用: 装饰器的本质:一个闭包函数 (高阶函数+嵌套函数) 装饰器的功能:在不修改原函数及其调用方式的情况下对原函数功能进行扩展 闭包原理 装饰器执行流程 带多个参数函数 import ...

  5. centos下安装pip时失败:

    [root@wfm ~]# yum -y install pipLoaded plugins: fastestmirror, refresh-packagekit, securityLoading m ...

  6. bug-3——onload,onbeforeunload,Onunload的区别

    window.onload事件设置页面加载时执行的动作,即进入页面的时候执行的动作.   window.onunload已经从服务器上读到了需要加载的新的页面,在即将替换掉当前页面时调用 一般用于设置 ...

  7. Android Resources

    Ref:Android开发最佳实践 Ref:Android高手速成--第一部分 个性化控件(View) Ref:Android高手速成--第二部分 工具库 Ref:Android高手速成--第三部分 ...

  8. C# unicode GBK UTF-8和汉字互转

    界面: 源码: using System; using System.Collections.Generic; using System.ComponentModel; using System.Da ...

  9. 3.11课·········异常语句与for循环重复

    异常语句try catch finally try//保护执行里面的代码段,若其中一句有错误,直接跳转到catch,不会管下面的内容 { Console.Write("请输入一个整数&quo ...

  10. spring boot项目使用swagger-codegen生成服务间调用的jar包

    swagger-codegen的github:https://github.com/swagger-api/swagger-codegen 需要的环境:jdk > 1.7   maven > ...