Stop Killing Your Database with @Transactional in Spring Boot
The 1-minute fix that slashed my API response time by 40%. We all know @Transactional makes database work easy. But are you using it correctly? Here is a mistake I see in 8 out of 10 code reviews: ❌ The Anti-Pattern: @Service public class OrderService { @Transactional public Order placeOrder ( OrderDto dto ) { Order order = new Order (); // 1. Save the parent orderRepository . save ( order ); //…
Spring Boot developers often rely on the @Transactional annotation to simplify database operations. However, a common mistake can inadvertently slow down their applications. In eight out of ten code reviews, they see developers mishandling transactions.
The issue arises when developers save parent objects and child objects within the same @Transactional method. For example, in an OrderService class, a loop saves child items one by one within the transaction. This results in an inefficient N+1 problem, where Hibernate makes a separate database round trip for each child item, leading to 50 unnecessary queries for 50 items.
The solution lies in refactoring the code. By adding a few properties to application.properties and modifying the code to use .saveAll(), developers can batch insert child items into the database. In the application.properties file, they should include:
spring.jpa.properties.hibernate.jdbc.batch_size = 50
spring.jpa.properties.hibernate.order_inserts = true
spring.jpa.properties.hibernate.order_updates = true
These settings instruct Hibernate to batch insert statements and order them correctly. In the code, instead of saving each child item individually, developers create a list of new Item objects, each linked to the parent Order object. Then, they save all items in one go using itemRepository.saveAll(items).
After implementing these changes, the performance improves dramatically. What was once 51 SQL queries for 50 items now only requires 2 queries. This results in a 40% faster response time and significantly reduced database load.
The key takeaway is that while @Transactional manages the transaction lifecycle, it doesn't automatically batch queries. Developers must explicitly tell Hibernate to batch them using configuration properties and appropriate code changes.
The discussion question posed by the author is: What's the one Spring Boot property you can't live without? Share your answer in the comments below.
Written by urgent.news from Dev.to's reporting — not their text. Machine-written — may contain errors; check the original before relying on it.