I didn’t expect duplicate data to become this tricky. Recently, while working on a backend feature, I noticed something off, the same data was getting stored multiple times in the database. When I tried to fetch it, I was getting duplicate records. At first, I thought it was just a one-time issue. But after checking further, it turned out to be happening consistently in certain cases. The root cause was multiple requests hitting the same flow, and there were no proper checks or validations to prevent duplicate inserts. To fix this, I made a few changes: - Added validation before inserting data - Introduced unique constraints at the database level - Handled edge cases where repeated requests could happen After that, the duplicates stopped, and the data became more reliable. It was a good reminder for me: Relying only on application logic is not enough. Both validation and the database should enforce rules where it matters. Sometimes, clean data is not just about writing correct code. It’s about designing the system to prevent mistakes. #Java #BackendDevelopment #Database #SystemDesign #SpringBoot #LearningInPublic
Preventing Duplicate Data in Database with Validation and Constraints
More Relevant Posts
-
Spent 25 minutes wondering why my @Transactional was not rolling back on exception The service method threw an exception but the data was still saved to the database Checked the logs and the transaction was committing anyway The problem was I was catching the exception inside the method @Transactional public void saveUser(User user) { try { userRepository save(user); throw new RuntimeException("Something went wrong"); } catch (Exception e) { log.error("Error saving user", e); } } Spring only rolls back when the exception propagates out of the method If you catch it inside, Spring thinks everything is fine and commits The fix was letting the exception propagate or using TransactionAspectSupport to mark rollback manually @Transactional public void saveUser(User user) { try { userRepository save(user); throw new RuntimeException("Something went wrong"); } catch (Exception e) { TransactionAspectSupport.currentTransactionStatus().setRollbackOnly(); log.error("Error saving user", e); } } Small detail but can cause serious data integrity issues What transaction gotcha has caught you before #Java #SpringBoot #Transactions #Debugging #BackendDevelopment
To view or add a comment, sign in
-
⚡ A simple thing that improved my API performance While working on a backend API, I noticed the response time was higher than expected. The issue wasn’t complex logic — it was this: 👉 Fetching unnecessary data from the database Here’s what I changed: ✔ Avoided using SELECT * ✔ Fetched only required fields ✔ Reduced multiple DB calls ✔ Added proper indexing Result? 🚀 Faster response time 🚀 Better performance 💡 Lesson: Small optimizations in database queries can make a big difference in real-world applications. What’s one small change that improved your system performance? 👇 #Java #SpringBoot #BackendDevelopment #SQL #Performance #Microservices
To view or add a comment, sign in
-
The N+1 problem happens when your application fetches a list of entities with one query, but then triggers an additional query for each item when accessing related data—often due to lazy loading in ORMs like JPA. What looks like a simple loop in code can result in dozens or hundreds of database calls, increasing latency, stressing the connection pool, and degrading performance under load. It’s not a logic bug but a data access design issue, where the way data is fetched doesn’t match how it’s used, causing the system to quietly slow down as scale increases #Java #SpringBoot #JPA #Hibernate #SystemDesign #Performance #BackendEngineering #Microservices #SoftwareEngineering #Scalability 🔥 Your loop has 1 line → Your database executes 100 queries ⚠️ Works perfectly in dev → Breaks silently under real traffic 📉 Not a logic bug → A hidden data access design flaw 🚨 Lazy loading = invisible performance killer 🧠 N+1 is not a loop problem → It’s a query shape problem 🔥 One-Line Takeaway Your loop didn’t break performance. Your data access pattern did.
To view or add a comment, sign in
-
-
Most transaction bugs in Spring Boot are not SQL bugs—they’re transaction boundary bugs. Today’s focus is a deep dive into @Transactional: propagation, isolation, and rollback rules. If you only use the default settings everywhere, you may accidentally create hidden data inconsistencies or unexpected commits. Example: @Service public class PaymentService { @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class) public void processPayment(Order order) { paymentRepository.save(new Payment(order.getId(), order.getTotal())); inventoryService.reserve(order.getItems()); } } Key idea: REQUIRED joins an existing transaction or starts a new one, REQUIRES_NEW creates a separate one, and isolation controls visibility of concurrent changes. By default, rollback happens for unchecked exceptions, so checked exceptions often need explicit rollbackFor. Treat @Transactional as an architectural decision, not just an annotation. #Java #SpringBoot #BackendDevelopment
To view or add a comment, sign in
-
-
Most transaction bugs in Spring Boot are not SQL bugs—they’re transaction boundary bugs. Today’s focus is a deep dive into @Transactional: propagation, isolation, and rollback rules. If you only use the default settings everywhere, you may accidentally create hidden data inconsistencies or unexpected commits. Example: @Service public class PaymentService { @Transactional(propagation = Propagation.REQUIRED, isolation = Isolation.READ_COMMITTED, rollbackFor = Exception.class) public void processPayment(Order order) { paymentRepository.save(new Payment(order.getId(), order.getTotal())); inventoryService.reserve(order.getItems()); } } Key idea: REQUIRED joins an existing transaction or starts a new one, REQUIRES_NEW creates a separate one, and isolation controls visibility of concurrent changes. By default, rollback happens for unchecked exceptions, so checked exceptions often need explicit rollbackFor. Treat @Transactional as an architectural decision, not just an annotation. #Java #SpringBoot #BackendDevelopment
To view or add a comment, sign in
-
-
One of our APIs started getting slower over time. At first, nothing looked wrong. It was working fine in dev. But as data increased, response time kept going up 📈 After digging a bit, we found the issue. Inside a loop, we were calling the database for every item. So one request was actually triggering 100+ queries 😅 Turns out, this is a classic N+1 query problem. Didn’t notice it early on because the data was small. But once it grew, it started hurting performance. We fixed it by changing it to a single query (join/batch). Same logic. Way better performance 🚀 Small thing, but big impact. Made me realize how easy it is to miss these issues when things “seem fine”. Now I always keep an eye on how many DB calls an API is making 👀 #BackendEngineering #Java #Performance #Database #Microservice
To view or add a comment, sign in
-
Is your @Transactional annotation actually doing what you think? 🧐 In Spring Boot, data integrity is everything. But I often see a common trap: Self-invocation. If you call a transactional method from another method within the same class, the Spring Proxy is bypassed. 📉 The result? No transaction starts, and your data might end up inconsistent without any error message. Check: ✅ The Proxy Rule: Spring uses AOP proxies. External calls go through the proxy; internal calls don't. ✅ The Fix: Move the transactional logic to a separate Service or use AspectJ if complexity scales. ✅ Bonus: Always use readOnly = true for fetch operations to improve performance and avoid unnecessary flush calls. It’s not just about using the framework; it’s about understanding the "Magic" behind it. 🚀 Have you ever faced a "phantom" database bug because of this? Let's swap stories! 👇 #Java #SpringBoot #Backend #Database #CleanCode #SoftwareEngineering #JavaDeveloper
To view or add a comment, sign in
-
-
🚨 One of the most dangerous Spring Boot traps — silent data loss with zero errors. @Transactional on a private method does absolutely nothing. No exception. No warning. Just broken data. ❌ Broken: @Service public class OrderService { public void placeOrder(Order order) { saveOrder(order); } @Transactional // ← silently ignored! private void saveOrder(Order order) { orderRepo.save(order); auditRepo.save(new AuditLog(order)); } } Why does this happen? Spring wraps beans in a proxy to intercept @Transactional calls. But private methods are invisible to the proxy — the call goes direct, completely bypassing transaction management. Result → partial saves, missing audit logs, inconsistent state. The fix: Keep transactional methods public. ✅ Fixed: @Service public class OrderService { @Transactional // ← proxy intercepts correctly public void saveOrder(Order order) { orderRepo.save(order); auditRepo.save(new AuditLog(order)); } } What makes this a production nightmare: → Unit tests pass cleanly → Logs show no errors → Only caught when data is already missing Spring won't warn you. The annotation just silently does nothing. Save this before it saves you. 🔖 Know any other silent Spring Boot traps? Drop them below 👇 #SpringBoot #Java #BackendDevelopment #SoftwareEngineering #CleanCode
To view or add a comment, sign in
-
-
Is your @Transactional annotation actually doing what you think? 🧐 In Spring Boot, data integrity is everything. But I often see a common trap: Self-invocation. If you call a transactional method from another method within the same class, the Spring Proxy is bypassed. 📉 The result? No transaction starts, and your data might end up inconsistent without any error message. Check: ✅ The Proxy Rule: Spring uses AOP proxies. External calls go through the proxy; internal calls don't. ✅ The Fix: Move the transactional logic to a separate Service or use AspectJ if complexity scales. ✅ Bonus: Always use readOnly = true for fetch operations to improve performance and avoid unnecessary flush calls. It’s not just about using the framework; it’s about understanding the "Magic" behind it. 🚀 Have you ever faced a "phantom" database bug because of this? Let's swap stories! 👇 hashtag #Java #SpringBoot #Backend #Database #CleanCode #SoftwareEngineering #JavaDeveloper
To view or add a comment, sign in
-
-
🚀 One Small Change That Improved My API Performance Not every improvement comes from rewriting the whole system. Sometimes, it’s just one small fix. I once worked on an API that looked fine in development, but started slowing down under real traffic. After digging deeper, the issue wasn’t the code… 👉 It was the database queries. Here’s what helped 👇 • Added proper indexing to frequently used columns • Reduced unnecessary joins • Selected only required fields instead of entire tables • Introduced caching for repeated requests Result? ⚡ Response time dropped from seconds → milliseconds 💡 Lesson: Before scaling your system, optimize what you already have. 💬 What’s one small change that made a big impact in your system? #BackendDevelopment #SQL #PerformanceOptimization #SystemDesign #Java #APIs #SoftwareEngineering
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
Adding one more point.. Using a UNIQUE constraint at the database level is one of the most effective ways to prevent duplicate records. It reliably enforces uniqueness, even under high concurrency or millions of insert attempts