Mybatis Dynamic SQL - 重新定义 Mybatis 动态 SQL
文章目录
通过全新的 ByExample 方法快速了解一下这是什么:
|
|
快速开始
- 新的动态SQL需要额外依赖
mybatis-dynamic-sql
- Java 8 及以上
- MyBatis 3.4.2 及以上
|
|
使用 MyBatis Generator
Info
MyBatis Generator 1.3.6 及以上
Info
1.3.6 在动态 SQL 模式下存在数个已修复的 BUG,建议使用 1.3.7 及以上版本。
|
|
只需要将 context 的 targetRuntime 属性更改为 MyBatis3DynamicSQL 即可生成新的动态 SQL
|
|
MyBatis3DynamicSQL 模式具有以下特性:
- 不再生成 XML,
<sqlMapGenerator>
将被忽略 - mapper 总是以注解形式实现,
<javaClientGenerator>
的 type 属性将被忽略 - model 类总是以 FLAT 形式生成
实例演示
我们用下面这张表来演示一下实际的生成结果。
|
|
MyBatis Generator 将会生成下述三个文件:
- 与表对应的 model 类
Employee.java
- 定义了表信息和列信息的 support 类
EmployeeDynamicSqlSupport.java
- 以注解形式实现的 mapper 接口
EmployeeMapper.java
Info
为了节省版面移除了一些代码,源代码可点击查看
我们暂时先不去关心具体的内部实现,大致看一下生成文件的样貌,之后先来了解如何使用这些文件。
model
|
|
support
|
|
mapper
|
|
如何使用
未变的方法
以下方法跟之前生成的代码具有一样的效果:
deleteByPrimaryKey
insert
- null 属性将会被插入insertSelective
- 忽略 nullselectByPrimaryKey
updateByPrimaryKey
- null 属性将会被设置updateByPrimaryKeySelective
- 忽略 null
全新的 ByExample
而 ByExample 方法则完全是另一种工作方式。像是下面这样:
|
|
未指定 WHERE 子句时自然是对表中所有行生效。
为了定制 WHRER 子句,在需要使用 mapper 接口的类中写入以下两条导入语句:
|
|
- 前者导入生成的 support 类,这样我们就能够使用
id
,employee.id
这样的字段 - 后者提供了用于构造 SQL 语句的
or
,and
,isEqualTo
等方法
|
|
MyBatis Dynamic SQL
Tip
这一部分的内容主要来自 MyBatis Dynamic SQL 文档,只少不多,直接阅读文档是个好主意的说
正如 MyBatis Generator 生成的文件,为了使用 MyBatis Dynamic SQL 你至少需要这三个文件:
- model 类
- 定义了表信息和列信息的 support 类
- 基于 XML 或注解实现的 mapper 接口
model 类和 support 类的编写可以参考上述生成的文件,而基本的 mapper 接口实际上只需要下述这些代码。
|
|
回顾一下生成的 mapper 接口,你会发现其他 default 方法实际上都是对这些方法的封装。为了使用这些原始方法,需要传入一个完整的语句,像是下面这样:
|
|
WHERE
- WHRER 子句支持各种各样的条件(参考附录 I)
- 能够任意组合 and 与 or
- 大多数条件也支持子查询
|
|
SELECT
目前已经支持的:
- 一些典型的 SELECT 元素 (SELECT, DISTINCT, FROM, JOIN, WHERE, GROUP BY, UNION, ORDER BY)
- 每条 SELECT 语句都能为表设置别名
- 每条 SELECT 语句都能为列设置别名
- 一些聚集函数 (avg, min, max, sum)
- 表连接 (INNER, LEFT OUTER, RIGHT OUTER, FULL OUTER)
- WHERE 子句中的子查询,如
where foo in (select foo from foos where id < 36)
尚未支持的:
- WITH 表达式
- HAVING 表达式
- SELECT 另一 SELECT 的结果,如
select count(*) from (select foo from foos where id < 36)
- INTERSECT,EXCEPT 等。
JOIN 查询
|
|
如果有必要,你可以为表指定别名。如果没有指定别名,将会使用 tableName.column
这种形式。
可以在单个语句中连接多个表。例如:
|
|
由于 MyBatis 注解的局限性,联表查询时你可能需要在 XML 中定义 resultMap。这是唯一需要 XML 的情况。
Note
文档的建议是:resultMap 应该是 XML 文件中唯一出现的元素。(但也只是文档的建议→_→)
UNION 查询
|
|
支持任意数量的 UNION 查询,但只允许一个 ORDER BY。
关于 Order By
如果存在别名列,别名表,UNION 和 JOIN,Order By 的处理会变得很困难。MyBatis Dynamic SQL 库采取了一个简单的方法 —— 将列别名或者列名写入 Order By 子句,表别名(如果存在的话)将会被忽略。
Question
In our testing, this caused an issue in only one case. When there is an outer join and the select list contains both the left and right join column. In that case, the workaround is to supply a column alias for both columns.
这一句话理解不能…就把原文放在这里了…还望看客大佬们提点 (〃ノωノ)
当使用函数(lower,upper 等)时,习惯上会给计算结果设置一个别名。这种情况下,可以使用 sortColumn
为 Order By 指定列名,如下所示:
|
|
DELETE
|
|
INSERT
|
|
注意 map
方法,它用于将数据库列映射到要插入记录的属性。有这几种不同的映射方法可用:
map(column).toNull()
将插入 nullmap(column).toConstant(constant_value)
将插入常量(直接写入生成的 INSERT 语句中)map(column).toStringConstant(constant_value)
将插入常量(被单引号'
包裹)map(column).toProperty(property)
将插入 record 的属性值map(column).toPropertyWhenPresent(property, Supplier<?> valueSupplier)
仅当 record 的属性值不是 null 时插入,这被用来生成 selective 方法
UPDATE
|
|
注意 set
方法,它用于设置数据库列的值。它的几种变体拥有与上述 map
方法相似的性质:
set(column).equalToNull()
set(column).equalToConstant(String constant)
set(column).equalToStringConstant(String constant)
set(column).equalTo(T value)
set(column).equalTo(Supplier<T> valueSupplier)
set(column).equalToWhenPresent(T value)
set(column).equalToWhenPresent(Supplier<T> valueSupplier)
XML mapper
虽然不推荐,但你仍然可以使用 xml mapper,它看起应该是这样的:
|
|
xml 文件应该是这样:
|
|
Rendering Strategies
RenderingStrategy 决定生成 SQL 参数占位符的格式,目前内置了两种策略:
RenderingStrategy.MYBATIS3
:适配 MyBatis3,生成#{param,jdbcType=INTEGER}
RenderingStrategy.SPRING_NAMED_PARAMETER
:适配 Spring NamedParameterJDBCTemplate, 生成:param
针对 MyBatis3 的特别支援
|
|
正如前文 MyBatis Generator 生成的诸多 ByExample 方法,这些方法仅包括一些样板式代码,它们返回一个还在构造中的语句,调用者可以可选的任意定制 WHRER 子句。
附 I:SqlBuilder
COMMENT | SQL |
---|---|
statements | deleteFrom , insert , insertInto , select , selectDistinct , update , where |
where condition connectors | or , and |
join support | and , equalTo |
aggregate support | count , max , min , avg , sum |
functions | add , lower , substring , upper |
conditions for all data types | isNull , isNotNull , isEqualTo , isNotEqualTo , isGreaterThan , isGreaterThanOrEqualTo , isLessThan , isLessThanOrEqualTo , isIn , isNotIn , isBetween , isNotBetween |
conditions for strings only | isLike , isLikeCaseInsensitive , isNotLike , isNotLikeCaseInsensitive , isInCaseInsensitive , isNotInCaseInsensitive |
order by support | sortColumn |
Reference
文章作者 olOwOlo
上次更新 2018-11-06