Reputation: 377
I have 2 different repositories in the same Spring Boot project.
I would like to define different batch sizes for the 2 different repositories. However, I could not find any solution for Spring Data Jpa config.
The repositories are given below:
@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);
}
The batch size configuration is given below
jpg:
spring:
properties:
hibernate:
jdbc:
batch_size: 4
order_inserts: true
order_updates: true
Is it possible configuring the batch sizes that way? If it is possible, how can I implement this?
Upvotes: 3
Views: 7733
Reputation: 13041
Theoretically you can try to implement BatchBuilder interface for example in the following way:
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 );
}
}
and then add the following properties to your spring application config:
spring.jpa.properties.hibernate.jdbc.batch.builder=com.your.app.MyBatchBuilder
spring.jpa.properties.hibernate.jdbc.batch_size=4
But as it's stated in the hibernate documentation, it is almost never a good idea to switch from Hibernate’s default implementation. So, maybe suggested in the comment approach will be more preferable for your needs.
P.S. Also as it's stated in the hibernate documentation:
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 );
Upvotes: 3