MyBatis Statement Builders

2024-01-24 14:18
文章标签 statement mybatis builders

本文主要是介绍MyBatis Statement Builders,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

Statement Builders

Request For Translation

This section is outdated in the Chinese version. Please refer to the English manual. Any help with the Chinese translation will be really welcome.

SelectBuilder

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

MyBatis 3 引入了一些不同的理念来处理这个问题,我们可以创建一个类的实例来调用其中的方法来一次构建 SQL 语句。但是我们的 SQL 结尾时看起来很像 Java 代码而不是 SQL 语句。相反,我们尝试了一些不同的做法。最终的结果是关于特定领域语言的结束,Java 也不断实现它目前的形式...

SelectBuilder 的秘密

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

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

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

private String selectPersonSql() {BEGIN(); // Clears ThreadLocal variableSELECT("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 variableSELECT("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 variableDELETE_FROM("PERSON");WHERE("ID = ${id}");return SQL();
}public String insertPersonSql() {BEGIN(); // Clears ThreadLocal variableINSERT_INTO("PERSON");VALUES("ID, FIRST_NAME", "${id}, ${firstName}");VALUES("LAST_NAME", "${lastName}");return SQL();
}public String updatePersonSql() {BEGIN(); // Clears ThreadLocal variableUPDATE("PERSON");SET("FIRST_NAME = ${firstName}");WHERE("ID = ${id}");return SQL();
}

这篇关于MyBatis Statement Builders的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/639955

相关文章

MyBatis常用XML语法详解

《MyBatis常用XML语法详解》文章介绍了MyBatis常用XML语法,包括结果映射、查询语句、插入语句、更新语句、删除语句、动态SQL标签以及ehcache.xml文件的使用,感兴趣的朋友跟随小... 目录1、定义结果映射2、查询语句3、插入语句4、更新语句5、删除语句6、动态 SQL 标签7、ehc

MyBatis延迟加载与多级缓存全解析

《MyBatis延迟加载与多级缓存全解析》文章介绍MyBatis的延迟加载与多级缓存机制,延迟加载按需加载关联数据提升性能,一级缓存会话级默认开启,二级缓存工厂级支持跨会话共享,增删改操作会清空对应缓... 目录MyBATis延迟加载策略一对多示例一对多示例MyBatis框架的缓存一级缓存二级缓存MyBat

mybatis直接执行完整sql及踩坑解决

《mybatis直接执行完整sql及踩坑解决》MyBatis可通过select标签执行动态SQL,DQL用ListLinkedHashMap接收结果,DML用int处理,注意防御SQL注入,优先使用#... 目录myBATiFBNZQs直接执行完整sql及踩坑select语句采用count、insert、u

MyBatis Plus大数据量查询慢原因分析及解决

《MyBatisPlus大数据量查询慢原因分析及解决》大数据量查询慢常因全表扫描、分页不当、索引缺失、内存占用高及ORM开销,优化措施包括分页查询、流式读取、SQL优化、批处理、多数据源、结果集二次... 目录大数据量查询慢的常见原因优化方案高级方案配置调优监控与诊断总结大数据量查询慢的常见原因MyBAT

MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决

《MyBatis/MyBatis-Plus同事务循环调用存储过程获取主键重复问题分析及解决》MyBatis默认开启一级缓存,同一事务中循环调用查询方法时会重复使用缓存数据,导致获取的序列主键值均为1,... 目录问题原因解决办法如果是存储过程总结问题myBATis有如下代码获取序列作为主键IdMappe

MyBatis分页查询实战案例完整流程

《MyBatis分页查询实战案例完整流程》MyBatis是一个强大的Java持久层框架,支持自定义SQL和高级映射,本案例以员工工资信息管理为例,详细讲解如何在IDEA中使用MyBatis结合Page... 目录1. MyBATis框架简介2. 分页查询原理与应用场景2.1 分页查询的基本原理2.1.1 分

MyBatis Plus实现时间字段自动填充的完整方案

《MyBatisPlus实现时间字段自动填充的完整方案》在日常开发中,我们经常需要记录数据的创建时间和更新时间,传统的做法是在每次插入或更新操作时手动设置这些时间字段,这种方式不仅繁琐,还容易遗漏,... 目录前言解决目标技术栈实现步骤1. 实体类注解配置2. 创建元数据处理器3. 服务层代码优化填充机制详

mybatis映射器配置小结

《mybatis映射器配置小结》本文详解MyBatis映射器配置,重点讲解字段映射的三种解决方案(别名、自动驼峰映射、resultMap),文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定... 目录select中字段的映射问题使用SQL语句中的别名功能使用mapUnderscoreToCame

mybatis-plus如何根据任意字段saveOrUpdateBatch

《mybatis-plus如何根据任意字段saveOrUpdateBatch》MyBatisPlussaveOrUpdateBatch默认按主键判断操作类型,若需按其他唯一字段(如agentId、pe... 目录使用场景方法源码方法改造首先在service层定义接口service层接口实现总结使用场景my

MyBatis ParameterHandler的具体使用

《MyBatisParameterHandler的具体使用》本文主要介绍了MyBatisParameterHandler的具体使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参... 目录一、概述二、源码1 关键属性2.setParameters3.TypeHandler1.TypeHa