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
Preventing Stale Reads with clearAutomatically in Spring
More Relevant Posts
-
Request life cycle (focused on Transactional, Hibernate, JPA & HikariCP) 1. Client sends HTTP request (POST /api/v1/orders) 2. OS receives TCP bytes → places in socket buffer 3. Tomcat picks up bytes → parses HTTP headers & body 4. Tomcat assigns request to a thread 5. Jackson deserialises JSON → Java object 6. Request routed to matching Controller via @RequestMapping 7. Controller validates input → calls Service 8. @Transactional proxy intercepts → opens DB connection → BEGIN 9. Service applies business logic → calls Repository 10. Spring Data JPA reads method name → generates JPQL 11. JPQL handed to EntityManager → Hibernate translates to SQL 12. Hibernate checks L1 cache → cache miss → sends SQL to MySQL 13. MySQL parses SQL → optimiser picks execution plan 14. InnoDB reads rows from disk/buffer → sends result back 15. Hibernate maps columns → @Entity Java object → stored in L1 cache 16. Service persists new data → Hibernate generates INSERT/UPDATE 17. MySQL executes write → acquires row locks → acknowledges 18. Method returns → @Transactional proxy intercepts → COMMIT 19. MySQL flushes to redo log → releases locks 20. Connection returned to HikariCP pool → L1 cache discarded 21. Controller wraps result → Jackson serialises to JSON 22. Tomcat writes HTTP response → OS sends TCP bytes back 23. Client receives response ✓ I love correlating all applications with kernel, so included sockets. If you want to know in depth correlation then I can mention page cache, fsync, thread life cycle, connection life cycle with port & overall kernel interaction at surface level in above lifecycle sequentially from next time :)
To view or add a comment, sign in
-
🚨 Performance Issues with Hibernate (and how to avoid them) Hibernate is powerful—but if you’re not careful, it can quietly destroy your application's performance. After working on large-scale systems, these are the most common issues I keep seeing: 🔴 1. N+1 Query Problem You fetch a list… and Hibernate fires one query per item. 👉 Example: Loading 100 orders = 101 queries 💥 Impact: Massive latency + database overload ✅ Fix: ▫️ Use JOIN FETCH ▫️ Use @EntityGraph ▫️ Consider DTO projections 🔴 2. LazyInitializationException (and bad fixes) Developers often switch everything to EAGER to "fix" it. 💥 Impact: Over-fetching → memory waste + slow queries ✅ Fix: ▫️ Keep LAZY by default ▫️ Control fetching explicitly in queries 🔴 3. Too Many SELECTs (chatty persistence layer) Multiple small queries instead of one optimized query. 💥 Impact: Network overhead + DB stress ✅ Fix: ▫️ Batch fetching (hibernate.default_batch_fetch_size) ▫️ Use IN queries ▫️ Optimize relationships 🔴 4. Missing Indexes Hibernate won’t save you from bad database design. 💥 Impact: Full table scans on large datasets ✅ Fix: ▫️ Add indexes on foreign keys and filters ▫️ Analyze execution plans 🔴 5. Dirty Checking Overhead Hibernate tracks all managed entities. 💥 Impact: High memory + CPU usage in large transactions ✅ Fix: ▫️ Use @Transactional(readOnly = true) when possible ▫️ Clear persistence context (EntityManager.clear()) 🔴 6. Uncontrolled Flushes Hibernate flushes more often than you expect. 💥 Impact: Extra queries + slower transactions ✅ Fix: ▫️ Use FlushModeType.COMMIT ▫️ Control flush manually in batch operations 🔴 7. Fetching Entire Entities When You Only Need a Few Fields Loading full objects when only 2–3 fields are needed. 💥 Impact: Memory waste + unnecessary joins ✅ Fix: ▫️ Use DTO projections (SELECT new ...) ▫️ Native queries when needed 💡 Final Thought Hibernate doesn’t make your app slow 👉 misusing Hibernate does. If you're building high-performance systems, you must understand what’s happening behind the scenes. 💬 Have you ever debugged a Hibernate performance issue in production? What was the root cause? #Java #Hibernate #Performance #Backend #SpringBoot #CleanCode
To view or add a comment, sign in
-
-
Recently, while working with Spring Boot and Hibernate, I came across a very common performance issue called the N+1 query problem. At first, everything looked fine. I was fetching all orders using: List<Order> orders = orderRepository.findAll(); This runs just one query on the orders table. But later, when I tried to access the customer information inside a loop: for (Order order : orders) { System.out.println(order.getCustomer().getName()); } Hibernate started firing one extra query for each order because of lazy loading. So if there are 100 orders, instead of 1 query, it becomes 101 queries. That’s when I understood how easily performance can be affected if we don’t pay attention to fetch strategies. To solve this, I explored a few approaches: 1. JOIN FETCH (Most Common) Fetch parent and child entities in a single query: @Query("SELECT o FROM Order o JOIN FETCH o.customer") List<Order> findAllOrdersWithCustomer(); This generates: SELECT o.*, c.* FROM orders o JOIN customer c ON o.customer_id = c.id; Now only 1 query runs instead of 101. 2. @EntityGraph A cleaner Spring Data JPA solution: @EntityGraph(attributePaths = {"customer"}) List<Order> findAll(); This tells Hibernate to fetch customer along with orders. Very clean and avoids custom JPQL. 3. Batch Fetching (@BatchSize) Very useful for @OneToMany relationships. @OneToMany(mappedBy = "customer") @BatchSize(size = 20) private List<Order> orders; Instead of firing one query per customer, Hibernate fetches in batches: SELECT * FROM orders WHERE customer_id IN (1,2,3,...20) This significantly reduces query count. 4. DTO Projection Best for API responses when only selected fields are needed. @Query(""" SELECT new com.example.dto.OrderDto( o.id, c.name ) FROM Order o JOIN o.customer c """) List<OrderDto> findAllOrderDtos(); This is fast, efficient, and avoids unnecessary entity loading. Learning things like this makes backend development really interesting for me — sometimes the code works perfectly, but under the hood it may still be inefficient. #SpringBoot #Hibernate #Java #BackendDevelopment #SoftwareEngineering #LearningJourney
To view or add a comment, sign in
-
🚨 Struggling with Performance Issues in Hibernate / Spring Data JPA? You might be facing the N+1 Problem! As Java developers, we often focus on writing clean business logic—but performance bottlenecks silently creep in through ORM behavior. One of the most common (and dangerous) issues? 👉 N+1 Query Problem --- 🔍 What is it? When your application executes: ✔️ 1 query to fetch parent entities ❌ + N additional queries to fetch child entities 👉 Result: N+1 total queries → serious performance degradation --- ⚠️ Why should you care? - Massive DB calls - Slow response time - High latency in microservices - Poor scalability under load --- 💡 Root Cause Default LAZY loading in ORM frameworks like Hibernate ORM triggers multiple queries when accessing relationships inside loops. --- 🔥 How to Solve It (Production-Ready Approaches) ✅ JOIN FETCH (Most Effective) → Fetch everything in a single query ✅ EntityGraph → Clean and flexible fetching strategy ✅ Batch Fetching → Reduces queries using IN clause batching ✅ DTO Projection → Fetch only required data (best for APIs) --- 📊 Real Impact Example Without optimization: 👉 100 records = 101 queries With optimization: 👉 100 records = 1 query --- 🧠 Pro Tip Always monitor SQL logs and understand how your ORM behaves internally. --- 🎯 Rule of Thumb “Fetch only what you need, when you need it — but do it efficiently.” --- I’ve created a detailed cheat sheet covering: ✔️ Problem breakdown ✔️ Internal working ✔️ Best solutions ✔️ Interview explanation --- #Java #SpringBoot #Hibernate #BackendDevelopment #Microservices #PerformanceOptimization #TechInterview #SoftwareEngine
To view or add a comment, sign in
-
-
🚀43/100 - N+1 Problem in Hibernate If you’re working with JPA/Hibernate, you are likely facing this without realizing it. What is N+1 Problem 🔸1 query to fetch parent data (Department) 🔸N queries to fetch child data (Employees) 🔸Total → N + 1 queries 🔸Fetching 5 departments → triggers 6 queries Why does this happen 🔸Root cause = Lazy Loading 🔸Hibernate does NOT fetch related data initially 🔸It loads a proxy (placeholder) 🔸When accessed → fires a query 🔸Access inside loop → multiple queries → N+1 Where it usually happens 🔹OneToMany relationships 🔹Looping over entities 🔹Returning entities directly in APIs 🔹Nested object access Why this is a problem 🔸Multiple DB hits → performance degradation 🔸Increased latency 🔸Heavy load on database 🔸Not scalable for large datasets How to solve this Spring Boot Approach (Recommended) 🔸@EntityGraph(attributePaths = "employees") 🔸Forces single query fetch Hibernate / JPQL Approach 🔸JOIN FETCH Example: SELECT d FROM Department d JOIN FETCH d.employees Other Approaches 🔸DTO Projection → fetch only req data 🔸Batch Fetching → reduces queries 🔸Avoid blind EAGER loading Key takeaway 🔹Lazy loading is not bad 🔹Lazy loading + loop = N+1 problem 🔹Always control how data is fetched I’ve created a complete backend developer guide covering: 🔸What is N+1 problem (with examples) 🔸Why it happens (deep dive - lazy loading) 🔸Real code (Entity, Repo,Service,Controller) 🔸With vs Without N+1 execution 🔸EntityGraph vs Fetch Join 🔸Multiple optimization approaches 🔸Diagrams for clear understanding Worth going through if you're preparing for backend interviews or building scalable APIs. Save & Repost🔁 if this helps someone preparing seriously Follow Surya Mahesh Kolisetty for more backend and Java deep dives #Java #SpringBoot #Hibernate #BackendDevelopment #JPA #SystemDesign #Performance #InterviewPreparation #SoftwareEngineering #CodingInterview #Developers #TechLearning #CFBR #SystemDesign #MicroServices
To view or add a comment, sign in
-
I spent weeks writing SQL by hand. Then I met Hibernate. Then Spring Boot. Now I can’t go back. Here’s what changed 👇 Raw JDBC → Hibernate → Spring Boot Data JPA It’s not just “less code.” It’s a completely different mental model. What Hibernate gave me: No more raw SQL for basic operations. You write Java. Hibernate translates. session.persist(empleado); // INSERT session.merge(empleado); // UPDATE session.remove(empleado); // DELETE Zero SQL written by hand. ✅ HQL lets you query objects, not tables. It felt like a superpower. Then Spring Boot Data JPA walked in. empleadoRepository.save(empleado); empleadoRepository.findById(id); empleadoRepository.deleteById(id); That’s it. No SessionFactory. No transaction boilerplate. No session.close(). Spring manages it all. So when does each one make sense? 🔹 Raw JDBC — when you need full control, complex custom queries, or you’re working in a legacy codebase. Not glamorous, but powerful. 🔹 Hibernate (standalone) — when you want ORM without a full framework. Great for learning the fundamentals before Spring. 🔹 Spring Boot + JPA — for real-world apps where speed and maintainability matter. This is what most companies actually use. ⚠️ The traps nobody warns you about: • Spring Boot hides so much — if you skip Hibernate basics, you won’t understand why things break • N+1 query problem: fetching a list of entities that each trigger extra queries = silent performance killer • Lazy loading outside a transaction = LazyInitializationException (classic first-week Spring error) • @Transactional is not optional — forget it and your data won’t save when you think it will The magic is real. But the magic has rules. Learn Hibernate first. Then let Spring Boot automate it. Building this in IntelliJ with Java — and every topic feels like unlocking a new level 🎮 hashtag #Java hashtag #Hibernate hashtag #SpringBoot hashtag #JPA hashtag #DesarrolloBackend hashtag #DAM
To view or add a comment, sign in
-
-
I spent weeks writing SQL by hand. Then I met Hibernate. Then Spring Boot. Now I can’t go back. Here’s what changed 👇 Raw JDBC → Hibernate → Spring Boot Data JPA It’s not just “less code.” It’s a completely different mental model. What Hibernate gave me: No more raw SQL for basic operations. You write Java. Hibernate translates. session.persist(empleado); // INSERT session.merge(empleado); // UPDATE session.remove(empleado); // DELETE Zero SQL written by hand. ✅ HQL lets you query objects, not tables. It felt like a superpower. Then Spring Boot Data JPA walked in. empleadoRepository.save(empleado); empleadoRepository.findById(id); empleadoRepository.deleteById(id); That’s it. No SessionFactory. No transaction boilerplate. No session.close(). Spring manages it all. So when does each one make sense? 🔹 Raw JDBC — when you need full control, complex custom queries, or you’re working in a legacy codebase. Not glamorous, but powerful. 🔹 Hibernate (standalone) — when you want ORM without a full framework. Great for learning the fundamentals before Spring. 🔹 Spring Boot + JPA — for real-world apps where speed and maintainability matter. This is what most companies actually use. ⚠️ The traps nobody warns you about: • Spring Boot hides so much — if you skip Hibernate basics, you won’t understand why things break • N+1 query problem: fetching a list of entities that each trigger extra queries = silent performance killer • Lazy loading outside a transaction = LazyInitializationException (classic first-week Spring error) • @Transactional is not optional — forget it and your data won’t save when you think it will The magic is real. But the magic has rules. Learn Hibernate first. Then let Spring Boot automate it. Building this in IntelliJ with Java — and every topic feels like unlocking a new level 🎮 #Java #Hibernate #SpringBoot #JPA #DesarrolloBackend #DAM
To view or add a comment, sign in
-
-
Really interesting perspective on the trade-offs between Spring Data JPA and JDBC. In my experience working with backend systems, this balance between abstraction and control is always a challenge. While ORMs like JPA make development faster, they can sometimes hide what’s really happening at the SQL level, especially when dealing with performance issues. Tools like jOOQ are interesting because they give you more control over queries while still keeping the benefits of type safety and integration with Java. I think the key is choosing the right tool based on the problem—especially when performance and complex queries are involved. Curious to hear—have you used jOOQ in production, and how was your experience?
💡 Java Object-Oriented Querying. 👉 In terms of database access, the Java community is clearly divided into two camps: some like Spring Data JPA for its simplicity and low entry threshold. In contrast, others prefer Spring JDBC for its accuracy and query-tuning capabilities. 👉 Both Spring Data JPA and Spring Data JDBC, with their obvious advantages, have disadvantages that make development on them not very suitable for production. These solutions are two extremes, and we need a golden mean. 🔥 You may ask: What are the alternatives? And I will answer: Java Object-Oriented Querying. ⚠️ jOOQ (Java Object-Oriented Querying) is a Java library that allows you to write SQL queries directly in your code using a typed DSL (Domain-Specific Language) generated based on the database schema. When used with Spring Boot, jOOQ provides strong typing, query safety, and convenient database operations, making it an excellent alternative to ORMs like Hibernate for complex queries. 🔥 Unlike Spring Data JPA, jOOQ has no side effects. There is no N+1 problem (unless, of course, you create one yourself with suboptimal queries). All queries will be executed exactly as you define them and in exactly the number you specify. ➕ Benefits: ▪️ Code generation: jOOQ scans your database and generates Java classes corresponding to the tables and views. ▪️ Type safety: If you change a column name in the database, the project will not compile until you update the queries, which prevents runtime errors. ▪️ SQL-oriented: Unlike Hibernate (which hides SQL), jOOQ allows you to write full-fledged, complex SQL queries (JOINs, subqueries, window functions) in Java, while retaining control over what happens. ▪️ Integration with Spring: Spring Boot automatically configures jOOQ components, supporting transactions and mapping results to POJOs (Plain Old Java Objects). 🔥 DSL frameworks solve the problem of “translation” between Java and SQL, allowing you to write a database query in a Java-based architecture in such a way that it exactly matches the expected SQL query. ‼️ Examples: Result<Record> result = create..select() .from(AUTHOR) .where(AUTHOR..ID..gt(5)) .orderBy(AUTHOR..FIRST_NAME..asc()) .fetch(); for (Record r: result) { Integer id = r.getValue(AUTHOR..ID); String firstName = r.getValue(AUTHOR.FIRST_NAME); logger.log(Level..INFO, "ID: {}, Name: {}", id, firstName); } 📌 jOOQ is the perfect choice if you need full control over SQL but want to avoid manual JDBC data mapping and typos in SQL queries. #programmingtips #softwaredevelopment #data #spring
To view or add a comment, sign in
-
-
Yesterday we talked about how Lombok can crash your app through Hibernate relationships. Today, let’s talk about the other silent killer in those exact same entities: The N+1 Query Problem. If you work with Spring Data JPA long enough, you will eventually write a piece of code that looks completely fine, passes all unit tests, and then completely chokes your database in production. Usually, the culprit is the N+1 problem. The Trap: Let’s say you have a User entity with a @OneToMany relationship to Order. You want to fetch 100 users and print their order totals. You write a simple repository call: userRepository.findAll() (This is 1 query).Then, you loop through those 100 users and call user.getOrders(). What you think happens: Hibernate fetches the users and their orders efficiently. What actually happens: Because relationships are (and should be!) FetchType.LAZY by default, Hibernate executes 1 query to get the 100 users, and then 100 additional queries—one for each user—to fetch their orders. You just hit your database 101 times for a single API request. Multiply that by 1,000 concurrent users, and your DBA is calling you in a panic. 😅 The Senior Fixes: 1. The Quick Fix: JOIN FETCH Instead of using standard findAll(), write a custom JPQL query: SELECT u FROM User u JOIN FETCH u.orders This forces Hibernate to grab everything in a single, efficient JOIN query. 2. The Elegant Fix: @EntityGraph If you don't want to write custom queries, Spring Boot lets you use Entity Graphs to dynamically define which lazy associations should be fetched eagerly for a specific method call. 3. The Ultimate Fix: DTO Projections Stop fetching full Managed Entities if you just need to read data! Write a query that maps directly to a Record or DTO. It bypasses the Hibernate proxy lifecycle entirely and is blazing fast. JPA makes the easy things trivial, but it makes the hard things incredibly dangerous if you don't look at the generated SQL. What is your team's standard way of catching N+1 queries before they hit production? Do you use a specific tool, or rely on code reviews? 👇 #Java #SpringBoot #Hibernate #BackendDevelopment #Microservices #SoftwareEngineering #PerformanceTuning #CleanCode
To view or add a comment, sign in
-
🚀 Stop Manual Updates: The Magic of Hibernate Dirty Checking ✔️Ever wondered why your database updates even when you never called .save()? ✔️That’s not a bug; it’s one of Hibernate’s most powerful features. 🎭 The 4 Stages of an Entity’s Life ➡️ Think of Hibernate states as a "VIP Club" for your Java objects. 1️⃣. Transient (The Outsider) ✔️ The object is just a regular Java object. Hibernate doesn't even know it exists. ✔️It has no ID and no connection to the database. ✔️Example: User user = new User("JavaDev"); ✔️Just sitting in your RAM, minding its own business. 2️⃣. Persistent (The VIP Member) ✔️You’ve called .save() or .persist(). The object is now "Managed." ✔️Hibernate is officially "watching" every single change you make to this object. ✔️Example:session.save(user); ✔️Hibernate now tracks this user in its internal cache. 3️⃣. Detached (The Former Member) ✔️The Session is closed. ✔️ The object still has its data and its Database ID, but the "link" is broken. ✔️Hibernate has stopped watching. ✔️Example: session.close(); ✔️ If you change user.setName() now, nothing happens in the database. 4️⃣. Removed (The Evicted) ✔️The object is scheduled to be deleted. ✔️It’s still in your code for a moment, but it’s headed for the exit. ✔️Example: session.delete(user); ✔️ It will be wiped from the DB once the transaction commits. ✨ The "Dirty Checking" Secret ✔️Dirty Checking is the reason you can write cleaner code. ✔️When an object is in the Persistent state, Hibernate takes a "snapshot" of it. ✔️When the transaction is about to finish (Commit), Hibernate performs a quick comparison: 🔹Snapshot:Name: "Rahul" 🔹Current Object: Name: "Rahul Kumar" ✔️Hibernate detects the "Dirt": Aha! The name changed. I’ll handle the SQL update for you! 💡 Why should you care? 1️⃣.Cleaner Code: Your methods aren't cluttered with unnecessary .save() calls. 2️⃣. Performance:Hibernate is smart; if nothing actually changed (no "dirt" found), it won't even fire the SQL update. 3️⃣.Consistency:It ensures your Java memory and Database stay in perfect sync. ✔️What’s your favorite "hidden" Hibernate feature? Let’s discuss in the comments! 👇 #Java #Hibernate #SpringBoot #BackendDevelopment #CodingTips
To view or add a comment, sign in
-
Explore content categories
- Career
- Productivity
- Finance
- Soft Skills & Emotional Intelligence
- Project Management
- Education
- Technology
- Leadership
- Ecommerce
- User Experience
- Recruitment & HR
- Customer Experience
- Real Estate
- Marketing
- Sales
- Retail & Merchandising
- Science
- Supply Chain Management
- Future Of Work
- Consulting
- Writing
- Economics
- Artificial Intelligence
- Employee Experience
- Workplace Trends
- Fundraising
- Networking
- Corporate Social Responsibility
- Negotiation
- Communication
- Engineering
- Hospitality & Tourism
- Business Strategy
- Change Management
- Organizational Culture
- Design
- Innovation
- Event Planning
- Training & Development