Day 26. I stopped using @Data in my JPA entities. Not because it doesn't work. Because it was breaking things I didn’t understand. I used to write this: // ❌ Looks clean — hides real problems @Data @Entity public class User { @Id private Long id; @OneToMany(mappedBy = "user") private List<Order> orders; } Looks clean. Less code. Everything auto-generated. Until it didn’t. Here’s what actually happens: → toString() triggers lazy loading → Infinite recursion in bidirectional relationships → Unexpected database queries → Hard-to-debug logs That’s when it clicked. @Data is not made for entities. It generates: → equals() → hashCode() → toString() And those methods don’t play well with JPA proxies and relationships. So I changed it. (see implementation below 👇) What I learned: → Lombok is powerful — but not always safe → Entities are not simple POJOs → Generated methods can silently break your system The hard truth: → @Data works in tutorials → It fails in real systems → Most developers don’t notice until production Writing less code is easy. Writing safe code is what makes you a backend developer. Are you still using @Data in entities? 👇 #SpringBoot #Java #Hibernate #BackendDevelopment #CleanCode #JavaDeveloper
{ "title": "Why I Stopped Using @Data in JPA Entities"
More Relevant Posts
-
🚀 Mastering Persistence in Spring Data JPA: persist() vs. merge() vs. save() Ever wondered which method to use when saving data in Java? Choosing the wrong one can lead to unnecessary SQL queries or even dreaded EntityExistsException errors. Here is the breakdown of the "Big Three": 🔹 1. persist() – The "New Only" Approach What it does: Takes a brand-new (transient) entity and makes it managed. It schedules an INSERT. Best for: Creating new records when you are sure they don't exist yet. Watch out: It will throw an exception if the entity is already detached or has an ID that exists in the DB. 🔹 2. merge() – The "Reconnector" What it does: Takes a detached entity (one that was loaded in a different session) and copies its state onto a new managed version. Best for: Updating existing records that were passed through different layers of your app (e.g., from a REST controller). Watch out: It creates a copy. You must use the returned object for further changes! 🔹 3. save() – The Spring Data Way What it does: A smart wrapper provided by Spring Data JPA. It checks if the entity is "new." If yes, it calls persist(); if not, it calls merge(). Best for: Most standard repository patterns. It’s the "safe bet" for 90% of use cases. Watch out: Because it checks state first, it might trigger an extra SELECT query to decide whether to insert or update. 💡 Pro Tip: If you are building high-performance systems with massive inserts, using persist() directly via the EntityManager can sometimes be more efficient than the generic save() method. Check out the infographic below for a quick visual cheat sheet! 📊 #Java #SpringBoot #JPA #Hibernate #SoftwareEngineering #BackendDevelopment
To view or add a comment, sign in
-
-
🚀 Backend Learning | Understanding the N+1 Query Problem While working on backend systems, I recently explored a common performance issue in ORM frameworks — the N+1 Query Problem. 🔹 The Problem: • Fetching related data triggers multiple queries instead of one • Example: 1 query for parent + N queries for child records • Leads to performance degradation and increased DB load 🔹 What I Learned: • Happens frequently in Hibernate / JPA due to lazy loading • Causes unnecessary database calls • Impacts scalability under large datasets 🔹 How to Fix: • Use JOIN FETCH to fetch related data in a single query • Apply Entity Graphs where needed • Optimize queries based on use-case 🔹 Outcome: • Reduced number of database queries • Improved application performance • Better handling of large datasets Sometimes performance issues are not about logic — they are about how data is fetched. 🚀 #Java #SpringBoot #Hibernate #JPA #BackendDevelopment #SystemDesign #Performance #LearningInPublic
To view or add a comment, sign in
-
-
⚠️ 𝕋𝕙𝕖 ℕ+𝟙 ℙ𝕣𝕠𝕓𝕝𝕖𝕞 — 𝕋𝕙𝕖 𝕊𝕚𝕝𝕖𝕟𝕥 𝕂𝕚𝕝𝕝𝕖𝕣 𝕠𝕗 𝕐𝕠𝕦𝕣 𝔹𝕒𝕔𝕜𝕖𝕟𝕕 ℙ𝕖𝕣𝕗𝕠𝕣𝕞𝕒𝕟𝕔𝕖 Everything looks fine in your code… Until your database starts suffering. You write something simple: 𝐋𝐢𝐬𝐭<𝐎𝐫𝐝𝐞𝐫> 𝐨𝐫𝐝𝐞𝐫𝐬 = 𝐨𝐫𝐝𝐞𝐫𝐑𝐞𝐩𝐨𝐬𝐢𝐭𝐨𝐫𝐲.𝐟𝐢𝐧𝐝𝐀𝐥𝐥(); Seems harmless, right? But under the hood, Hibernate might be doing this: 1 query → fetch all orders N queries → fetch each related entity (customers, products, etc.) 💥 𝗥𝗲𝘀𝘂𝗹𝘁: * Dozens (or hundreds) of unnecessary queries. * Increased latency. * Heavy database load. Performance degradation under traffic And the worst part? You often don’t notice it… until it’s too late. 🧠 𝗪𝗵𝘆 𝘁𝗵𝗶𝘀 𝗵𝗮𝗽𝗽𝗲𝗻𝘀 ? Because of lazy loading. Hibernate tries to be smart and loads relationships only when needed. But in loops or collections… it turns into a query explosion. 🛠️ 𝗛𝗼𝘄 𝘁𝗼 𝗳𝗶𝘅 𝗶𝘁 (𝗽𝗿𝗼𝗽𝗲𝗿𝗹𝘆): ✔️ 𝐉𝐎𝐈𝐍 𝐅𝐄𝐓𝐂𝐇 : Load related data in a single optimized query. ✔️ @𝐄𝐧𝐭𝐢𝐭𝐲𝐆𝐫𝐚𝐩𝐡 : Control fetching strategy declaratively. ✔️ 𝗗𝗧𝗢 𝗣𝗿𝗼𝗷𝗲𝗰𝘁𝗶𝗼𝗻𝘀 : Fetch only what you actually need (best for performance-critical paths). 💡 𝗥𝗲𝗮𝗹 𝘁𝗮𝗸𝗲𝗮𝘄𝗮𝘆 Performance issues are rarely in your business logic. They’re often in: 👉 How you fetch your data. 👉 How many queries you execute. 👉 How your ORM behaves behind the scenes. Good backend engineers don’t just write code that works, they write code that scales under pressure. #SpringBoot #Java #BackendDevelopment #Hibernate #PerformanceOptimization #SystemDesign #CleanCode
To view or add a comment, sign in
-
-
🚨 𝗧𝗵𝗲 𝗦𝗶𝗹𝗲𝗻𝘁 𝗣𝗲𝗿𝗳𝗼𝗿𝗺𝗮𝗻𝗰𝗲 𝗞𝗶𝗹𝗹𝗲𝗿 𝗶𝗻 𝗦𝗽𝗿𝗶𝗻𝗴 𝗕𝗼𝗼𝘁 — 𝗡+𝟭 𝗤𝘂𝗲𝗿𝘆 𝗣𝗿𝗼𝗯𝗹𝗲𝗺 Everything works fine… Until your API suddenly becomes slow in production 😅 That’s when many discover the N+1 Query Problem. 𝗪𝗵𝗮𝘁 𝗶𝘀 𝗡+𝟭? You fetch 1 parent entity Then Hibernate runs N additional queries for child entities 👉 Total queries = N + 1 👉 Performance = 📉 𝗘𝘅𝗮𝗺𝗽𝗹𝗲 Fetching Departments with Employees: Instead of 1 query, Hibernate runs: • 𝟭 𝗾𝘂𝗲𝗿𝘆 → Fetch departments • 𝗡 𝗾𝘂𝗲𝗿𝗶𝗲𝘀 → Fetch employees for each department Boom 💥 Performance issue. 𝗖𝗼𝗺𝗺𝗼𝗻 𝗠𝗶𝘀𝘁𝗮𝗸𝗲 A common instinct is to switch to EAGER loading to fix it. But… ❌ EAGER can also cause N+1 ❌ More memory usage ❌ Less control 𝗕𝗲𝘁𝘁𝗲𝗿 𝗦𝗼𝗹𝘂𝘁𝗶𝗼𝗻𝘀 ✅ ✔️ JOIN FETCH Fetch everything in a single query ✔️ EntityGraph Cleaner and more flexible approach ✔️ Batch Size Reduces queries for large datasets ✔️ DTO Projection Best for read-only APIs and performance Understanding this early can save hours of debugging in production 🚀 #connections #SpringBoot #Hibernate #Java #Backend #Performance #JPA #SoftwareEngineering #interviewPrep #interviewQuestion
To view or add a comment, sign in
-
-
I used to think using Spring Data JPA meant I didn’t really need to worry about SQL anymore. It felt too easy. 😅 I remember building a feature that looked perfectly fine in code, clean repositories, simple method names, everything “just worked.” Until I started testing it with more data and suddenly the API got slower… and slower. 🐢 Not crashing. Not failing. Just… slower. I opened the logs and saw a flood of queries. One for users, then one for each user’s orders. 📄📄📄 That’s when it hit me, I had no idea what queries were actually running behind my code. That moment was a bit uncomfortable everything “worked”, but I clearly didn’t understand what was happening. 😬 A few things became very real after that: JPA hides complexity, but it doesn’t remove it 🎭 JPA makes things easy, but it doesn’t make database behavior go away ⚠️ Just because you didn’t write the query doesn’t mean it’s efficient. You still need to understand what’s being generated 🔍 Lazy vs eager loading isn’t just theory, it directly impacts performance ⚙️ That innocent looking repository method? It can cause an N+1 problem real quick 🚨 In real systems, this doesn’t show up during basic testing. It shows up as slow endpoints, high DB usage and confusing debugging sessions. 🧩 Now, I still use JPA the same way but I don’t trust it blindly. I check queries, think about fetching strategies and pay attention to what’s happening underneath. 👨💻 What I learned: If you’re using JPA without understanding the queries, you are debugging in the dark. Have you ever been surprised by what JPA was doing behind the scenes? 🤔 #Java #SoftwareEngineer #SpringMVC #SpringBoot #SpringDataJPA
To view or add a comment, sign in
-
THE MIDDLE GROUND: MASTERING DYNAMIC FETCHING (PART 2) 🛡️🚀 How do you stay "Lazy" enough to be fast, but "Eager" enough to avoid N+1? The answer is Dynamic Fetching. 1. DEFAULT TO LAZY 💤 Set almost all your @OneToMany and @ManyToMany relationships to FetchType.LAZY. This keeps your basic "FindById" queries lightweight and fast. 2. FETCH ONLY WHAT YOU NEED 🎯 When you have a specific use case that needs the children, use a JOIN FETCH in your JPQL or HQL: SELECT u FROM User u JOIN FETCH u.orders WHERE u.id = :id This tells Hibernate: "I know this is usually lazy, but for this specific query, bring the orders back in the same trip." 3. ENTITY GRAPHS 📊 For complex structures, use JPA Entity Graphs. They allow you to define a "template" of what should be loaded eagerly for different API endpoints, without changing the global lazy/eager settings in your Entity class. THE TAKEAWAY: Don't let Hibernate make the decision for you. Keep your entities lightweight and fetch your data explicitly. A "one-size-fits-all" loading strategy is usually a one-way ticket to a production bottleneck. ✅ #Java #Hibernate #SpringDataJPA #BackendEngineering #SQL #SoftwareArchitecture
To view or add a comment, sign in
-
-
When I first started with Spring Data JPA, this honestly felt like magic User findByEmail(String email); No SQL . No implementation. No query. And somehow… it worked. I used it for a long time before asking How is this actually possible? When I started with Spring Boot, I assumed this was just framework magic and I think many of us have felt the same. But that skips the most interesting part. It is not magic. It is a parser. Spring treats this method name: findByEmail() as a mini query language. Yes — the method name itself. Internally, Spring Data uses a parser called PartTree to read it. It breaks it into meaning like - * find → create a select query * By → start parsing criteria * Email → match an entity property If your entity has - private String email; Spring can derive a query from the method name.That is called query derivation using naming conventions.And this is where it gets deeper.Spring does not directly generate SQL.It first derives JPQL.Then Hibernate converts JPQL into database-specific SQL. This getSomeUserStuff() does not work. Because the parser does not understand it. But this findByEmailAndStatus() works because it follows a grammar.That is not just convention. That is a contract. And one detail many of use miss - Spring validates these derived queries at startup. Not later. So if you write: findByEmailAddress() but your entity does not have - emailAddress , your application can fail fast during startup. That is intentional framework design. Sometimes the most elegant engineering is hiding inside the APIs we use every day. #SpringBoot #Java #JPA #Hibernate #BackendDevelopment
To view or add a comment, sign in
-
Over the past few days, I’ve been diving deep into how JPA and Spring Data JPA handle database interactions — and honestly, understanding the internals changed how I look at backend systems. Here are 3 core building blocks that clicked for me: 🔹 DataSource The foundation that provides database connections (driver, URL, credentials). Without it, nothing talks to the database. 🔹 EntityManagerFactory A heavyweight, thread-safe factory that bootstraps JPA and creates EntityManager instances. Think of it as the control center of persistence. 🔹 EntityManager The workhorse that manages the persistence context, handles CRUD operations, and interacts with the database. Not thread-safe — so each transaction gets its own instance. Behind every @Transactional annotation, there’s a powerful orchestration happening: 🔹Transaction Manager ensures commit/rollback 🔹Persistence Context tracks entity states (new, managed, detached, removed) 🔹PlatformTransactionManager abstracts everything across technologies #Java #SpringBoot #JPA #BackendDevelopment #FullStackDeveloper #Microservices #SystemDesign #HappyLearning #DeveloperLife #SoftwareEngineering #Coding
To view or add a comment, sign in
-
-
🧠 A follow-up on REST API design (and a common hidden issue) In a previous post, I mentioned why returning entities directly from the database can cause problems. One of the most common (and frustrating) ones in Spring-based applications is: ⚠️ LazyInitializationException This usually happens when: You expose entities directly You rely on ORM (like JPA/Hibernate) And a lazy relationship is accessed outside of a transaction 🚨 Suddenly, your API breaks… or you start adding quick fixes like: Changing relationships to EAGER Adding Open Session in View (OSIV) Forcing unnecessary queries 👉 All of these can hurt performance and scalability. 🚀 An alternative worth considering: Spring Data JDBC Instead of relying on a full ORM, Spring Data JDBC follows a simpler approach: No lazy loading No proxies No hidden queries You explicitly control what gets loaded. 💡 Why this can be powerful (especially in microservices): ✅ Predictable queries (what you load is what you get) ✅ Better performance (no unexpected joins or N+1 issues) ✅ Simpler mental model (less ORM magic) ✅ Fits well with small, focused microservices 🧠 In many cases, combining: DTOs for API responses Explicit data loading (instead of lazy ORM behavior) …can make your services more robust, faster, and easier to maintain. #Java #SpringBoot #Microservices #BackendDevelopment #SoftwareEngineering
To view or add a comment, sign in
-
🚀 How Spring Data JPA Works Internally Today I took some time to deeply understand how Spring Data JPA actually works behind the scenes. Most of the time, we simply write: studentRepository.findAll(); But internally, a lot happens: We create a Repository Interface Spring creates a Proxy Object for it The proxy intercepts the method call Hibernate converts it into an SQL query The SQL runs on the database The result is returned as Java objects Simple flow: Your Code → Repository → Proxy Class → Hibernate → SQL Query → Database This is what makes Spring Data JPA so powerful and developer-friendly. ✔ Less boilerplate code ✔ Automatic CRUD operations ✔ Query generation from method names ✔ Seamless Hibernate integration ✔ Faster backend development Example: List<Student> students = studentRepository.findAll(); Behind the scenes, Spring and Hibernate handle everything automatically. It may look like magic when you start learning backend development, but once you understand the internal flow, it becomes much easier to work with. #Java #SpringBoot #SpringDataJPA #Hibernate #BackendDevelopment #Programming #SoftwareEngineering #JavaDeveloper #Coding #WebDevelopment
To view or add a comment, sign in
-
Explore related topics
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
Hot take: @Data is one of the most dangerous annotations in Hibernate. Not because it’s wrong — but because it hides complexity you need to understand.