I'm trying to add a batch update to my spring boot project. But multiple queries are still executed when I check SQL logs and Hibernate stats.
Hibernate stats
290850400 nanoseconds spent acquiring 1 JDBC connections;
0 nanoseconds spent releasing 0 JDBC connections;
3347700 nanoseconds spent preparing 19 JDBC statements;
5919028800 nanoseconds spent executing 19 JDBC statements;
0 nanoseconds spent executing 0 JDBC batches;
0 nanoseconds spent performing 0 L2C puts;
0 nanoseconds spent performing 0 L2C hits;
0 nanoseconds spent performing 0 L2C misses;
2635900 nanoseconds spent executing 1 flushes (flushing a total of 1 entities and 0 collections);
19447300 nanoseconds spent executing 19 partial-flushes (flushing a total of 18 entities and 18 collections)
Versions
Spring Boot v2.7.1
Spring v5.3.21
Java 17.0.3.1
Oracle Database 12c Enterprise Edition Release 12.1.0.2.0 - 64bit Production
application.yml
spring:
datasource:
url: jdbc:oracle:thin:@localhost:1521/db
username: user
password: password
driver-class-name: oracle.jdbc.OracleDriver
jpa:
database-platform: org.hibernate.dialect.Oracle12cDialect
hibernate:
naming:
physical-strategy: org.hibernate.boot.model.naming.PhysicalNamingStrategyStandardImpl
ddl-auto: update
show-sql: true
properties:
hibernate:
dialect: org.hibernate.dialect.Oracle12cDialect
format_sql: false
jdbc:
fetch_size: 100
batch_size: 5
order_updates: true
batch_versioned_data: true
generate_statistics: true
Snapshot entity
@Entity
@Table(name = "SNAPSHOT", schema = "SYSTEM", catalog = "")
public class Snapshot {
@GeneratedValue(strategy = GenerationType.SEQUENCE)
@Id
@Column(name = "ID")
private long id;
@Basic
@Column(name = "CREATED_ON")
private String createdOn;
...
}
SnapshotRepository
@Repository
public interface SnapshotRepository extends JpaRepository<Snapshot, Long> {
@Modifying
@Query("UPDATE Snapshot s SET s.fieldValue =?1,s.createdOn=?2 where s.id = ?3 and s.fieldName = ?4")
int updateSnapshot(String fieldValue, String createdOn, String id, String fieldName);
}
And this repository method is called from the service class.
for (Map.Entry<String, String> entry : res.getValues().entrySet()) {
snapshotRepository.updateSnapshot(entry.getValue(), createdOn, id, entry.getKey());
}
pom.xml
<dependency>
<groupId>com.oracle.database.jdbc</groupId>
<artifactId>ojdbc11</artifactId>
<version>21.7.0.0</version>
</dependency>
In the application.yml, I think I'm configuring all required properties to activate batch update but still no luck.
Please let me know what I'm doing incorrectly.
flushbehaviour, in your case@Query("UPDATE ...performs direct updates in DB. Perhaps, you are modifying entities in memory, which forces HBN to flush their state prior issuing SQL update.snapshotRepository.save(snapshot)The batching works perfectly in this case.