2023-08-24 14:39:13 +08:00

128 lines
3.8 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 批量操作
在 MyBatis-Flex 中,提供了许多批量操作(批量插入、批量更新等)的方法,当有多个方法的时候,会经常导致误用的情况。
## `BaseMapper.insertBatch` 方法
这个方法的示例代码如下:
```java
List<Account> accounts = ....
mapper.insertBatch(accounts);
```
通过 `BaseMapper.insertBatch` 执行时,会通过 `accounts` 去组装一个如下的 SQL
```sql
insert into tb_account(id,nickname, .....) values
(100,"miachel100", ....),
(101,"miachel101", ....),
(102,"miachel102", ....),
(103,"miachel103", ....),
(104,"miachel104", ....),
(105,"miachel105", ....);
```
这种有一个特点:在小批量数据执行插入的时候,效率是非常高;但是当数据列表过多时,其生成的 SQL 可能会非常大, 这个大的 SQL
在传输和执行的时候就会变得很慢了。
因此,`BaseMapper.insertBatch` 方法只适用于在小批量数据插入的场景,比如 100 条数据以内。
## `Db.executeBatch` 方法
`Db.executeBatch` 可以用于进行批量的插入、修改和删除,以下是使用 `Db.executeBatch` 进行批量插入的示例:
```java
List<Account> accounts = ....
Db.executeBatch(accounts.size(), 1000, AccountMapper.class, (mapper, index) -> {
Account account = accounts.get(index);
mapper.insert(account);
});
```
或者
```java
List<Account> accounts = ....
Db.executeBatch(accounts, 1000, AccountMapper.class, (mapper, account) -> {
mapper.insert(account);
});
```
`Db.executeBatch` 是通过 JDBC 的 `Statement.executeBatch()` 进行批量执行;这个在大批量数据执行的时候,效率要比 `BaseMapper.insertBatch` 高出许多;
IService 很多批量操作的方法,也都是通过 `Db.executeBatch` 进行封装的,大家也可以通过其扩展出自己的 "批量操作" 方法来。比如这是一个批量忽略 `null` 的插入示例:
```java
public boolean saveBatchSelective(Collection<Account> entities) {
int[] result = Db.executeBatch(entities,
1000,
AccountMapper.class,
BaseMapper::insertSelective);
return SqlUtil.toBool(result);
}
```
------
**注意!注意!错误的用法!**
在社区里看到个别同学,在使用 `Db.executeBatch` 时,未使用到参数 mapper而是使用了其他 mapper或者使用了 UpdateChain 等。
如下所示:
```java
List<Account> accounts = ....
Db.executeBatch(accounts, 1000, AccountMapper.class
, (mapper, account) -> {
// ↑↑↑↑↑ 以上的这个 mapper未被使用
UpdateChina.of(account)
.set(Account::getUserName, "张三")
.update();
});
```
以上的 **错误** 示例,是因为没有用到 `mapper` 参数,因此,不仅仅 `Db.executeBatch` 返回的都是失败的内容,而且也起不到批量操作的作用。
## `Db.updateBatch` 方法
这个方法的示例代码如下:
```java
List<Account> accounts = ....
String sql = "insert into tb_account(user_name, age, birthday) " +
"values (?, ?, ?)";
Db.updateBatch(sql, new BatchArgsSetter() {
@Override
public int getBatchSize() {
return accounts.size();
}
@Override
public Object[] getSqlArgs(int index) {
Account account = accounts = accounts.get(index);
Object[] args = new Object[3];
args[0] = account.getUserName;
args[1] = account.getAge();
args[2] = new Date();
return args;
}
});
```
虽然这个方法叫 `updateBatch`,但一样可以执行 `insert``delete``update` 等任何 SQL 这个方法类似 Spring 的 `jdbcTemplate.batchUpdate()` 方法。
## `Db.updateEntitiesBatch` 方法
这个方法用于批量根据 id 更新 entity其是对 `Db.executeBatch` 的封装,使用代码如下:
```java
List<Account> accounts = ....
Db.updateEntitiesBatch(accounts, 1000);
```