MySQL的问题
1. 基本概念
在之前的文章中,我们反复强调,默认情况下,Jimmer不会为MySQL启用批量查询。这是因为MySQL对批量查询的支持存在两个缺陷:
-
必须在JDBC连接字符串中显式指定
rewriteBatchedStatements
才能开启MySQL的批量操作能力,例如jdbc:mysql://localhost:3306/mydb?rewriteBatchedStatements=true
警告如果不指定
rewriteBatchedStatements
,虽然JDBC的Batch操作仍然可以执行,但实际被调用的是虚假实现。 对性能没有任何帮助,本质上和使用多条SQL没有任何区别。 -
一旦真正启用了MySQL的批量操作,会丢失必要的返回信息,例如
-
无法返回JDBC的
generatedKeys
,这会导致无id属性的实体对象的id无法被自动填充,而这对基于自动编号的id分配策略而言是非常重要且常见的诉求 -
无法返回任何操作的影响行数
信息Jimmer称MySQL的这种批量操作为哑批操作。由于该操作会导致实质性的功能缺失
-
除非用户明确表示自己可以接受哑批操作,Jimmer不会采用MySQL的批量操作
-
即使用户明确表示自己可以接受哑批操作,Jimmer也只是尽量采用MySQL的批量操作,但不保证一定会。这也是本文要讨论的重点之一
-
2. 准备工作
2.1. 启用MySQL的批量操作
-
修改数据库连接字符串
为连接字符串指定
rewriteBatchedStatements
,例如jdbc:mysql://localhost:3306/mydb?rewriteBatchedStatements=true
-
为sqlClient开启明确的批量操作支持,存在如下两种等价的方法,任选其一
-
采用Jimmer的Spring Boot Starter
编辑
application.yml
或application.properties
,如下application.ymljimmer:
explicit-batch-enabled: true
...省略其他配置... -
采用Jimmer的核心API
- Java
- Kotlin
JSqlClient sqlCient = JSqlClient
.newBuilder()
.setExplicitBatchEnabled(true)
...省略其他配置...
.build();val sqlClient = sqlCient {
setExplicitBatchEnabled(true)
...省略其他配置...
}
-
2.2. 明确表示哑批操作可以接受
有两种方法可用于明确地向Jimmer表示哑批操作是可以接受的
-
全局配置 (不推荐)
全局配置又可分为两种
-
采用Jimmer的Spring Boot Starter
编辑
application.yml
或application.properties
,如下application.ymljimmer:
dumb-batch-acceptable: true
...省略其他配置... -
采用Jimmer的核心API
- Java
- Kotlin
JSqlClient sqlCient = JSqlClient
.newBuilder()
.setDumbBatchAcceptable(true)
...省略其他配置...
.build();val sqlClient = sqlCient {
setDumbBatchAcceptable(true)
...省略其他配置...
}
-
-
保存指令级配置 (推荐)
- Java
- Kotlin
List<Book> books = ...略...;
sqlClient
.saveEntitiesCommand(books)
.setDumbBatchAcceptable(true)
.execute();