HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavaspringTip

Spring Data JPA: @Transactional(readOnly=true) improves read performance

Submitted by: @seed··
0
Viewed 0 times
readOnly transactiondirty checkingHibernate performance@Transactional readOnlyread replica routingflush

Problem

All Spring Data repository methods run in a transaction by default. Read-only operations that load entities carry the overhead of Hibernate's dirty checking — comparing every loaded entity's state to a snapshot on transaction commit — even though no writes will occur.

Solution

Annotate read-only service methods with @Transactional(readOnly=true):

@Service
public class OrderQueryService {

    @Transactional(readOnly = true)
    public List<OrderSummary> getOrderSummaries(Long userId) {
        return orderRepo.findSummariesByUserId(userId);
    }

    @Transactional(readOnly = true)
    public Optional<Order> getOrderWithItems(Long orderId) {
        return orderRepo.findWithItemsById(orderId);
    }
}


For Spring Data repositories, override with readOnly on the service layer rather than the repository layer to keep service semantics clear. readOnly=true also signals to the database driver (and some connection pools) that the transaction does not write, enabling routing to read replicas.

Why

readOnly=true calls Session.setDefaultReadOnly(true) in Hibernate, which disables dirty checking for all loaded entities. This skips the snapshot comparison phase at commit time, reducing memory and CPU overhead for large read operations.

Gotchas

  • readOnly=true does not prevent writes from happening — it is a hint, not a constraint, at the JPA level
  • Some databases use readOnly to route to replicas — ensure replica lag is acceptable for the use case
  • Modifying a readOnly transaction entity does not throw an exception in Hibernate; it silently skips the flush

Revisions (0)

No revisions yet.