在 spring 数据 jpa 中为不同的存储库定义不同的批量大小
Define different batch sizes in spring data jpa for different repositories
我在同一个 Spring 引导项目中有 2 个不同的存储库。
我想为 2 个不同的存储库定义不同的批次大小。但是,我找不到 Spring Data Jpa 配置的任何解决方案。
存储库如下:
@Repository
public interface ItemRepository extends JpaRepository<Item, String> {
Page<Item> findItemByCreationDateBefore(Timestamp creationDate, Pageable pageable);
}
@Repository
public interface CarRepository extends JpaRepository<Car, String> {
@Query("SELECT c FROM Car c WHERE c.journeyCode = :journeyCode " +
"AND c.currentLocationId = :currentLocationId")
Page<Delivery> findCars(Long journeyCode, Long currentLocationId, Pageable pageable);
}
batch size配置如下
jpg:
spring:
properties:
hibernate:
jdbc:
batch_size: 4
order_inserts: true
order_updates: true
是否可以这样配置批量大小?如果可能的话,我该如何实现?
理论上您可以尝试通过以下方式实现 BatchBuilder 接口:
import java.util.Map;
import org.hibernate.cfg.Environment;
import org.hibernate.engine.jdbc.batch.internal.BasicBatchKey;
import org.hibernate.engine.jdbc.batch.internal.BatchBuilderMXBean;
import org.hibernate.engine.jdbc.batch.internal.BatchingBatch;
import org.hibernate.engine.jdbc.batch.spi.Batch;
import org.hibernate.engine.jdbc.batch.spi.BatchBuilder;
import org.hibernate.engine.jdbc.batch.spi.BatchKey;
import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.service.spi.Configurable;
import org.hibernate.service.spi.Manageable;
public class MyBatchBuilder implements BatchBuilder, Configurable, Manageable, BatchBuilderMXBean
{
private int jdbcBatchSize;
public MyBatchBuilder()
{
}
public MyBatchBuilder(int jdbcBatchSize) {
this.jdbcBatchSize = jdbcBatchSize;
}
@Override
public void configure(Map configurationValues) {
jdbcBatchSize = ConfigurationHelper.getInt( Environment.STATEMENT_BATCH_SIZE, configurationValues, jdbcBatchSize );
}
@Override
public int getJdbcBatchSize() {
return jdbcBatchSize;
}
@Override
public void setJdbcBatchSize(int jdbcBatchSize) {
this.jdbcBatchSize = jdbcBatchSize;
}
@Override
public Batch buildBatch(BatchKey key, JdbcCoordinator jdbcCoordinator)
{
final Integer sessionJdbcBatchSize = jdbcCoordinator.getJdbcSessionOwner()
.getJdbcBatchSize();
final int jdbcBatchSizeToUse = sessionJdbcBatchSize == null ?
this.jdbcBatchSize :
sessionJdbcBatchSize;
// getEntityName() + "#DELETE"
// getEntityName() + "#UPDATE"
BasicBatchKey insertCarBatchKey = new BasicBatchKey("com.your.entities.Car#INSERT", null);
final int jdbcBatchSizeForCar = 20;
if (insertCarBatchKey.equals(key))
{
return new BatchingBatch( key, jdbcCoordinator, jdbcBatchSizeForCar );
}
return new BatchingBatch( key, jdbcCoordinator, jdbcBatchSizeToUse );
}
}
然后将以下属性添加到您的 spring 应用程序配置中:
spring.jpa.properties.hibernate.jdbc.batch.builder=com.your.app.MyBatchBuilder
spring.jpa.properties.hibernate.jdbc.batch_size=4
但是正如 hibernate documentation 中所述,从 Hibernate 的默认实现切换几乎不是一个好主意。所以,也许在评论中建议的方式会更符合您的需求。
P.S。也正如休眠文档中所述:
Since version 5.2, Hibernate allows overriding the global JDBC batch size given by the hibernate.jdbc.batch_size
configuration property on a per Session
basis.
entityManager
.unwrap( Session.class )
.setJdbcBatchSize( 10 );
我在同一个 Spring 引导项目中有 2 个不同的存储库。
我想为 2 个不同的存储库定义不同的批次大小。但是,我找不到 Spring Data Jpa 配置的任何解决方案。
存储库如下:
@Repository
public interface ItemRepository extends JpaRepository<Item, String> {
Page<Item> findItemByCreationDateBefore(Timestamp creationDate, Pageable pageable);
}
@Repository
public interface CarRepository extends JpaRepository<Car, String> {
@Query("SELECT c FROM Car c WHERE c.journeyCode = :journeyCode " +
"AND c.currentLocationId = :currentLocationId")
Page<Delivery> findCars(Long journeyCode, Long currentLocationId, Pageable pageable);
}
batch size配置如下
jpg:
spring:
properties:
hibernate:
jdbc:
batch_size: 4
order_inserts: true
order_updates: true
是否可以这样配置批量大小?如果可能的话,我该如何实现?
理论上您可以尝试通过以下方式实现 BatchBuilder 接口:
import java.util.Map;
import org.hibernate.cfg.Environment;
import org.hibernate.engine.jdbc.batch.internal.BasicBatchKey;
import org.hibernate.engine.jdbc.batch.internal.BatchBuilderMXBean;
import org.hibernate.engine.jdbc.batch.internal.BatchingBatch;
import org.hibernate.engine.jdbc.batch.spi.Batch;
import org.hibernate.engine.jdbc.batch.spi.BatchBuilder;
import org.hibernate.engine.jdbc.batch.spi.BatchKey;
import org.hibernate.engine.jdbc.spi.JdbcCoordinator;
import org.hibernate.internal.util.config.ConfigurationHelper;
import org.hibernate.service.spi.Configurable;
import org.hibernate.service.spi.Manageable;
public class MyBatchBuilder implements BatchBuilder, Configurable, Manageable, BatchBuilderMXBean
{
private int jdbcBatchSize;
public MyBatchBuilder()
{
}
public MyBatchBuilder(int jdbcBatchSize) {
this.jdbcBatchSize = jdbcBatchSize;
}
@Override
public void configure(Map configurationValues) {
jdbcBatchSize = ConfigurationHelper.getInt( Environment.STATEMENT_BATCH_SIZE, configurationValues, jdbcBatchSize );
}
@Override
public int getJdbcBatchSize() {
return jdbcBatchSize;
}
@Override
public void setJdbcBatchSize(int jdbcBatchSize) {
this.jdbcBatchSize = jdbcBatchSize;
}
@Override
public Batch buildBatch(BatchKey key, JdbcCoordinator jdbcCoordinator)
{
final Integer sessionJdbcBatchSize = jdbcCoordinator.getJdbcSessionOwner()
.getJdbcBatchSize();
final int jdbcBatchSizeToUse = sessionJdbcBatchSize == null ?
this.jdbcBatchSize :
sessionJdbcBatchSize;
// getEntityName() + "#DELETE"
// getEntityName() + "#UPDATE"
BasicBatchKey insertCarBatchKey = new BasicBatchKey("com.your.entities.Car#INSERT", null);
final int jdbcBatchSizeForCar = 20;
if (insertCarBatchKey.equals(key))
{
return new BatchingBatch( key, jdbcCoordinator, jdbcBatchSizeForCar );
}
return new BatchingBatch( key, jdbcCoordinator, jdbcBatchSizeToUse );
}
}
然后将以下属性添加到您的 spring 应用程序配置中:
spring.jpa.properties.hibernate.jdbc.batch.builder=com.your.app.MyBatchBuilder
spring.jpa.properties.hibernate.jdbc.batch_size=4
但是正如 hibernate documentation 中所述,从 Hibernate 的默认实现切换几乎不是一个好主意。所以,也许在评论中建议的方式会更符合您的需求。
P.S。也正如休眠文档中所述:
Since version 5.2, Hibernate allows overriding the global JDBC batch size given by the
hibernate.jdbc.batch_size
configuration property on a perSession
basis.
entityManager
.unwrap( Session.class )
.setJdbcBatchSize( 10 );