JDBC batches reduce network calls, but a long transaction still retains managed entities unless the import flushes and clears deliberately.
JPA insert batching: bound both JDBC trips and persistence-context memory
Two different limits
Setting hibernate.jdbc.batch_size groups compatible DML statements for the driver. It does not cap the first-level persistence context. Importing thousands of receipt lines in one transaction can retain every managed object and its dirty-checking state until completion. Flushing writes pending SQL; clearing detaches managed entities. A flush is not a commit, and a later rollback still undoes the transaction.
Design chunk ownership
For a bounded import chunk, persist rows, then flush and clear at a measured interval. Do not rely on a previously managed parent after clear; reload it or use its stable identifier. When each chunk is an independent transaction, define restart and duplicate handling as part of the import contract. Identity-generated primary keys can prevent insert batching, because each insert may need its generated value immediately. Inspect actual JDBC batch statistics rather than assuming the property guarantees a speedup.
Measure with the target driver
Compare 47-row and 94-row chunks under the production database dialect and driver. Capture transaction duration, pool wait, memory and batch execution counts. A larger batch can reduce round trips while increasing lock hold time and rollback work. Pool capacity and committed chunk boundaries determine how much concurrent import work the database can absorb.
Implementation contract
spring.jpa.properties.hibernate.jdbc.batch_size=47
spring.jpa.properties.hibernate.order_inserts=true
// Within one bounded transaction:
for (int rowIndex = 0; rowIndex < receiptLines.size(); rowIndex++) {
entityManager.persist(receiptLines.get(rowIndex));
if ((rowIndex + 1) % 47 == 0) { entityManager.flush(); entityManager.clear(); }
}Cost and verification
Batched SQL can lower network round trips from roughly one per row toward one per group. First-level context memory still grows with managed objects between clears, while ordering inserts adds sorting work.
Common Mistakes
- Do not treat batch_size as a memory limit.
- Do not keep using an entity reference as managed after clear.
- Do not assume IDENTITY-generated inserts batch on the target provider and driver.
Read next
Spring Data JPA saveAndFlush is a SQL boundary, not a commit, Spring Batch chunks: a later failure does not erase an earlier commit, Spring Boot JDBC pool capacity: size connections across replicas, Spring JPA entity lifecycle: managed changes and detached objects, Spring Batch writers: use a stable source key when a chunk is replayed.
