MySQL Issues
1. Basic Concepts
As emphasized in previous articles, Jimmer does not enable batch queries for MySQL by default. This is because MySQL has two deficiencies in its support for batch queries:
-
The
rewriteBatchedStatementsparameter must be explicitly specified in the JDBC connection string to enable MySQL's batch operation capability, for example:jdbc:mysql://localhost:3306/mydb?rewriteBatchedStatements=truecautionIf
rewriteBatchedStatementsis not specified, although JDBC Batch operations can still be executed, it's actually using a fake implementation. It provides no performance benefits and is essentially no different from using multiple individual SQL statements. -
Once MySQL's batch operations are really enabled, necessary return information is lost, such as:
-
Cannot return JDBC's
generatedKeys, which means the id of entities without an id property cannot be automatically filled. This is a very important and common requirement for id allocation strategies based on SQL identity. -
Cannot return the number of affected rows for any operation
infoJimmer refers to this type of MySQL batch operation as a dumb batch operation. Due to the substantial loss of functionality:
-
Unless users explicitly indicate that they can accept dumb batch operations, Jimmer will not use MySQL batch operations
-
Even if users explicitly indicate that they can accept dumb batch operations, Jimmer will only try to use MySQL batch operations when possible, but does not guarantee it will always do so. This is one of the key points we'll discuss in this article.
-
2. Preparation
2.1. Enabling MySQL Batch Operations
-
Modify the database connection string
Specify
rewriteBatchedStatementsin the connection string, for example:jdbc:mysql://localhost:3306/mydb?rewriteBatchedStatements=true -
Enable explicit batch operation support for sqlClient, there are two equivalent methods, choose either:
-
Using Jimmer's Spring Boot Starter
Edit
application.ymlorapplication.propertiesas follows:application.ymljimmer:
explicit-batch-enabled: true
...other configurations omitted... -
Using Jimmer's Core API
- Java
- Kotlin
JSqlClient sqlClient = JSqlClient
.newBuilder()
.setExplicitBatchEnabled(true)
...other configurations omitted...
.build();val sqlClient = sqlClient {
setExplicitBatchEnabled(true)
...other configurations omitted...
}
-
2.2. Explicitly Indicating Acceptance of Dumb Batch Operations
There are two methods to explicitly indicate to Jimmer that dumb batch operations are acceptable:
-
Global Configuration (not recommended)
Global configuration can be done in two ways:
-
Using Jimmer's Spring Boot Starter
Edit
application.ymlorapplication.propertiesas follows:application.ymljimmer:
dumb-batch-acceptable: true
...other configurations omitted... -
Using Jimmer's Core API
- Java
- Kotlin
JSqlClient sqlClient = JSqlClient
.newBuilder()
.setDumbBatchAcceptable(true)
...other configurations omitted...
.build();val sqlClient = sqlClient {
setDumbBatchAcceptable(true)
...other configurations omitted...
}
-
-
Save Command Level Configuration (recommended)
- Java
- Kotlin
List<Book> books = ...omitted...;
sqlClient
.saveEntitiesCommand(books)
.setDumbBatchAcceptable(true)
.execute();val books = ...omitted...;
sqlClient.saveEntities(books) {
setDumbBatchAcceptable(true)
}infoYou can also use the simpler parameterless call
setDumbBatchAcceptable()
Explicitly indicating acceptance of dumb batch operations will result in substantial loss of functionality, so it's more recommended to enable it at the save command level
3. Simple Examples
3.1 Specifying Object IDs
Assuming jimmer.explicit-batch-enabled has been specified, execute the following code:
- Java
- Kotlin
List<Book> books = Arrays.asList(
Immutables.createBook(draft -> {
draft.setId(11L);
draft.setPrice(new BigDecimal("59.99"));
}),
Immutables.createBook(draft -> {
draft.setId(12L);
draft.setPrice(new BigDecimal("68.99"));
})
);
sqlClient
.saveEntitiesCommand(books)
.setMode(SaveMode.UPDATE_ONLY)
.setDumbBatchAcceptable()
.execute();
val books = listOf(
Book {
id = 11L
price = BigDecimal("59.99")
},
Book {
id = 12L
price = BigDecimal("68.99")
}
)
sqlClient.updateEntities(books) {
setDumbBatchAcceptable()
}
In this case, Jimmer will generate batch operation SQL for MySQL:
update BOOK
set PRICE = ?
where ID = ?
/* batch-0: [59.99, 11] */
/* batch-0: [57.99, 12] */