批处理

我们可以通过 transaction.setBatchMode(true) 显式启用 JDBC 批处理。

try (Transaction transaction = database.beginTransaction()) {

  // use JDBC batch
  transaction.setBatchMode(true);

  // these go to batch buffer
  aBean.save();
  bBean.save();
  cBean.save();

  // batched
  database.saveAll(someBeans);

  // flush batch and commit
  transaction.commit();
}

@Transactional(batchSize)

使用 @Transactional 设置 batchSize 属性将启用 JDBC 批处理。

@Transactional(batchSize = 50)
public void doGoodStuff() {

  ...
}

批处理大小

批处理大小控制 Ebean 在执行 JDBC 预处理语句之前绑定该语句的次数。在持久化 Bean(例如 customer.save())时,它实际上是持久化 Bean 的数量。

当 Bean(或 SqlUpdate 或 CallableSql)的数量达到批处理大小时,批处理将刷新,缓冲区中的所有语句都将执行。

在持久化不同类型的 Bean 时(例如“订单”和“订单详情”),当任何缓冲区达到批处理大小时,所有缓冲区都将刷新。这允许 Ebean 保留执行顺序,例如在持久化所有“订单”之前持久化所有“订单详情”。

批处理缓冲区大小的默认值通过 databaseConfig.persistBatchSize 设置,其默认值为 20。我们可以通过 transaction.setBatchSize()@Transactional(batchSize) 在事务中设置缓冲区大小。

try (Transaction transaction = database.beginTransaction()) {

  // use JDBC batch
  transaction.setBatchMode(true);
  transaction.setBatchSize(50);

  // these go to batch buffer
  aBean.save();
  ...

  // flush batch and commit
  transaction.commit();
}

GetGeneratedKeys

默认情况下,Ebean 将在插入 Bean 后获取生成的键。当我们有处理大量行/Bean 的插入,并且我们实际上不需要在插入后获取键时,我们可以关闭获取生成的键以提高性能。

// don't bother getting back the generated keys
transaction.setGetGeneratedKeys(false);

当我们执行大批量插入时,通常会关闭getGeneratedKeys

try (Transaction transaction = database.beginTransaction()) {
  transaction.setBatchMode(true);
  transaction.setBatchSize(100);

  // turn off GetGeneratedKeys as we don't need the keys
  transaction.setGetGeneratedKeys(false);

  // maybe even turn off persist cascade ...
  transaction.setPersistCascade(false)

  // perform lots of inserts ...
  ...


  transaction.commit();
}

刷新

批处理在以下情况下刷新

  • 缓冲区达到批处理大小
  • 我们执行查询 - 取决于 setFlushOnQuery()
  • 我们混合 SqlUpdate、CallableSql 与持久化 Bean - 取决于 setFlushOnMixed()
  • 我们对已批处理的 Bean 属性调用 getter 或 setter,例如 bean.getId()
  • 我们显式调用 flush()

setFlushOnQuery()

当我们想要执行查询但不想触发刷新时,在事务中设置 setFlushOnQuery(false)

try (Transaction transaction = database.beginTransaction()) {
  transaction.setBatchMode(true);
  transaction.setFlushOnQuery(false);

  // these go to batch buffer
  aBean.save();
  ...

  // execute this query but we don't
  // want that to trigger flush
  SomeOtherBean.find.byId(42);

  ...

  transaction.commit();
}

setFlushOnMixed()

当我们想要执行 SqlUpdate 或 CallableSql 混合 bean save()、delete() 等操作,并且不想触发刷新时,在事务中设置 setFlushOnMixed(false)

try (Transaction transaction = database.beginTransaction()) {
  transaction.setBatchMode(true);
  transaction.setFlushOnMixed(false);

  // these go to batch buffer
  aBean.save();
  ...

  // execute SqlUpdate but we don't
  // want that to trigger flush
  SqlUpdate update = ...
  update.execute();

  ...

  transaction.commit();
}

在 getter/setter 上刷新

对于批处理缓冲区中的 Bean,如果我们对生成属性或“未加载”Id 属性调用 getter/setter,这将触发刷新。

try (Transaction transaction = database.beginTransaction()) {
  transaction.setBatchMode(true);

  // bean goes to batch buffer
  myBean.save();
  ...

  // will trigger flush if id is an "unloaded" property
  // and myBean is in the buffer (not flushed)
  long id = myBean.getId();

  // will trigger flush if myBean is in the buffer (not flushed)
  Instant whenCreated = myBean.getWhenCreated();

  ...

  transaction.commit();
}

显式 flush()

当我们想要确保已执行任何批处理语句时,我们可能希望执行显式 transaction.flush()。这通常意味着我们知道已执行所有 SQL 语句,并且在应用程序逻辑中的该点测试了所有 DB 约束。

try (Transaction transaction = database.beginTransaction()) {
  transaction.setBatchMode(true);

  // bean goes to batch buffer
  myBean.save();
  ...


  // ensure all SQL statements are executed which means that
  // all DB constraints (unique, foreign key etc) are tested
  transaction.flush();


  // carry on with stuff ...
  ...

  transaction.commit();
}

通过 DatabaseConfig 配置

// use JDBC batch by default
databaseConfig.setPersistBatch(PersistBatch.ALL);

我们可以设置 databaseConfig.setPersistBatch(PersistBatch.ALL),以便 JDBC 批处理模式成为所有事务使用的默认模式。

// default batch size
databaseConfig.setPersistBatchSize(50);

我们可以通过 databaseConfig.setPersistBatchSize() 更改全局默认批处理大小。否则,默认设置为 20。

// update all loaded properties or just dirty properties
databaseConfig.setUpdateAllPropertiesInBatch(true);

在使用批处理更新时,我们有权选择在更新中包含脏属性或所有已加载属性。如果我们选择脏属性,我们将把较少的属性包含在更新语句中,但我们可能会得到更多正在执行的不同更新语句(在应用程序逻辑未更新正在更新的所有 Bean 上的相同属性的情况下)。