Careeroza
Read-Only Transactions
readOnly = true
Mark query-only service methods with @Transactional(readOnly = true). With Spring and Hibernate 6 this:
- sets the Hibernate session to read-only, so loaded entities keep no snapshot for dirty checking (less memory, faster);
- sets flush mode to
MANUAL, so accidental changes to entities are not written; - calls
Connection.setReadOnly(true), which lets drivers and routing data sources send the query to a read replica.
@Service
@Transactional(readOnly = true) // default for the whole class
@RequiredArgsConstructor
public class ProductQueryService {
private final ProductRepository products;
public Page<ProductCardDto> list(Pageable pageable) { ... } // read-only
@Transactional // overrides: read-write
public void updatePrice(Long id, BigDecimal price) { ... }
}A Change That Is Silently Ignored
Example
@Transactional(readOnly = true)
public ProductDto show(Long id) {
Product p = products.findById(id).orElseThrow();
p.setName(p.getName().trim().toUpperCase()); // bug: modifying inside a read-only tx
return ProductDto.from(p);
}Example output
DEBUG org.hibernate.SQL : select p1_0.id,p1_0.category_id,p1_0.description,p1_0.name,p1_0.price,p1_0.stock from products p1_0 where p1_0.id=? -- no UPDATE: the change is not flushed in a read-only transaction
Tip: Spring Data's SimpleJpaRepository is already annotated @Transactional(readOnly = true) for its find methods, and read-write for save/delete.