Preventing Stale Reads with clearAutomatically in Spring

Running native queries in Spring? Hibernate's L2 cache doesn't know about native queries. When you bypass JPQL and fire raw SQL directly, Hibernate has no way to track the changes made. The stale data quietly stays in the cache. The fix: clearAutomatically = true on @Modifying @Query(  value = "UPDATE products SET price = :price WHERE id = :id",  nativeQuery = true ) @Modifying(clearAutomatically = true) @Transactional int updatePrice(@Param("price") BigDecimal price, @Param("id") Long id); This evicts the entire persistence context (L1 cache) after the bulk update. So the next read goes back to the DB. Real-world scenarios where this matters: 1) Bulk price updates in e-commerce (without clear, the old price is returned) 2) Soft deletes via native UPDATE (cached entity still shows as "active") 3) Batch status/audit flag changes (stale flags break downstream logic silently) 4) In-app data migrations running native DML during startup or scheduled jobs Advantages: 1) Prevents stale reads after bulk DML 2) Keeps L1 cache consistent with DB state 3) Zero boilerplate - one annotation flag Disadvantages: 1) Evicts the entire persistence context - not just the affected rows 2) Triggers an implicit flush before eviction (can surface unexpected dirty checks) 3) Hurts performance in large, long-running transactions 4) Does not invalidate L2 cache (Ehcache, Redis) - handle that separately Note: Use clearAutomatically = true whenever native bulk DML touches data already loaded in your persistence context. For L2 cache invalidation, pair it with @CacheEvict or a manual eviction call. #Java #SpringBoot #SpringDataJPA #Hibernate #SoftwareEngineering

To view or add a comment, sign in

Explore content categories