Spring Boot DAY 21 –PathVariable vs RequestParam Understanding the difference between @PathVariable and @RequestParam is very important while building REST APIs 👇 Both are used to extract data from the URL, but they serve different purposes. --- 🔹 1️⃣ @PathVariable ✔ Used to extract values from the URL path ✔ Part of the resource identity ✔ Mandatory by default ✅ Example URL: /users/10 ✅ Code Example: java @GetMapping("/users/{id}") public String getUser(@PathVariable int id) { return "User ID: " + id; } 👉 Here, 10 is part of the URL path. 👉 It represents a specific resource (User with ID 10). 📌 Mostly used when: Fetching single record Updating a specific resource Deleting a specific resource --- 🔹 2️⃣ @RequestParam ✔ Used to extract values from query parameters ✔ Used for filtering, sorting, searching ✔ Can be optional ✅ Example URL: /users?id=10 ✅ Code Example: java @GetMapping("/users") public String getUserById(@RequestParam int id) { return "User ID: " + id; } 👉 Here, id=10 is passed as a query parameter. 👉 Mostly used for filtering or optional data. 📌 Example: /users?city=Nashik /users?page=1&size=5 /users?sort=asc 💡 When to Use What? 👉 Use @PathVariable when the value is required to uniquely identify a resource. 👉 Use @RequestParam when passing optional filters or additional parameters. 🎯 Interview Tip: If the data changes the identity of the resource → use PathVariable If the data modifies how results are returned → use RequestParam
Spring Boot PathVariable vs RequestParam
More Relevant Posts
-
4 things nobody tells you about JPA's @PrePersist and @PreUpdate: 1. @PreUpdate only fires if Hibernate actually issues an UPDATE. No field changed = no callback. 2. JPQL bulk updates bypass callbacks completely. Your timestamps won't refresh. 3. Don't call other repositories inside callbacks. That's how you get mysterious exceptions at 2 AM. 4. For pure audit fields, @EnableJpaAuditing is cleaner. Save @PrePersist for actual domain derivation, slugs, counts, computed fields. Full breakdown with code examples 👇 https://lnkd.in/guSfFfVV #Java #SpringBoot #JPA #Hibernate
To view or add a comment, sign in
-
🔹 Understanding autowire in Spring XML Configuration In Spring Framework, the autowire attribute helps automatically inject dependencies between beans — reducing manual configuration in XML. 📌 Why use autowire? It eliminates the need to explicitly define <property> or <constructor-arg> for every dependency. 💡 Types of Autowiring in Spring XML: 1️⃣ byName Spring matches the bean property name with the bean id. <bean id="employee" class="com.example.Employee" autowire="byName"/> <bean id="address" class="com.example.Address"/> 👉 Here, if Employee has a property named address, Spring injects the address bean. 2️⃣ byType Spring injects the bean based on the data type. <bean id="employee" class="com.example.Employee" autowire="byType"/> <bean id="address" class="com.example.Address"/> 👉 If only one bean of type Address exists, it gets injected automatically. 3️⃣ constructor Spring injects dependencies via constructor. <bean id="employee" class="com.example.Employee" autowire="constructor"/> 4️⃣ no (default) No autowiring. Dependencies must be defined manually. ⚠️ Important Notes: ✔ Works only if matching bean is available ✔ byType fails if multiple beans of same type exist ✔ Not recommended for large projects (Annotations like @Autowired are preferred) 🚀 Conclusion: autowire is useful for reducing XML configuration, but modern Spring applications mostly use annotation-based dependency injection. #SpringFramework #Java #BackendDevelopment #SpringBoot #CodingTips
To view or add a comment, sign in
-
🚀 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
-
-
One trace. 572,789 spans. 62% of all trace data in a five-minute sample, from a single service. This was a batch processing job. The #OpenTelemetry Java auto-instrumentation agent created a span for every database call inside a loop. The agent does not have a built-in span count cap per trace. It instruments what it finds, and a batch job iterating over hundreds of thousands of records will produce hundreds of thousands of spans. The trace was unusable. No backend renders half a million spans in a waterfall view. The cost was astronomical, and the four largest traces in the sample had no root span metadata, suggesting missing or disconnected parent spans. Most originated from batch or scheduled tasks like `https://lnkd.in/dBWthabm`. This organization runs 3,532 services, all on Java auto-instrumentation v1.33.6. The agent works well for request-response services. It was never designed for uncapped iteration over data. The fix depends on the batch pattern. For jobs that process items independently, use span links instead of parent-child relationships. Each item gets its own trace, linked back to the batch trace. This keeps individual traces small and queryable while preserving the connection to the batch context. For specific instrumentation that generates noise, the agent supports suppression flags. Setting `otel.instrumentation.common.experimental.suppress-messaging-receive-spans=true` eliminates receive spans for messaging consumers. Similar flags exist for JDBC, Redis, and other libraries. Review which instrumentations fire inside your loops and suppress the ones that add volume without insight. Auto-instrumentation assumes your services handle requests. When your workload does not fit that model, you need guardrails. The agent will not set them for you. And about last Friday's quiz: what does `stability: stable` mean for an OpenTelemetry semantic convention attribute? The answer is that it follows semver deprecation rules. A stable attribute is not frozen. It can still be deprecated, but the project must provide a migration path and maintain backward compatibility for a defined period. An `experimental` attribute carries no such guarantee and might be renamed or removed between releases. If you build dashboards or code generation around an experimental attribute, you accept the risk of breakage on upgrade.
To view or add a comment, sign in
-
📌 Collectors in Java Streams — Transforming Data Efficiently Collectors are used with streams to transform and gather results into collections or other structures. They are mainly used with: collect() — a terminal operation --- 1️⃣ What is collect()? collect() converts a stream into a final result like: • List • Set • Map • Grouped data Example: List<Integer> list = stream.collect(Collectors.toList()); --- 2️⃣ Common Collectors 🔹 toList() Convert stream to List list.stream() .collect(Collectors.toList()); --- 🔹 toSet() Removes duplicates list.stream() .collect(Collectors.toSet()); --- 🔹 toMap() Convert to Map list.stream() .collect(Collectors.toMap( key -> key.getId(), value -> value )); --- 3️⃣ groupingBy (Very Important) Groups elements based on a key Example: Map<String, List<Employee>> map = employees.stream() .collect(Collectors.groupingBy( e -> e.getDepartment() )); --- 4️⃣ counting() Counts elements long count = list.stream() .collect(Collectors.counting()); --- 5️⃣ joining() Joins strings String result = list.stream() .collect(Collectors.joining(", ")); --- 6️⃣ Why Collectors Are Powerful ✔ Transform data easily ✔ Replace complex loops ✔ Enable grouping and aggregation ✔ Improve readability --- 🧠 Key Takeaway Collectors turn streams into meaningful results. They are essential for data transformation and aggregation. #Java #Java8 #Streams #Collectors #BackendDevelopment
To view or add a comment, sign in
-
🔥 Part 2 of the series is live: We just implemented @Autowired from scratch. Not just reading about it. Actually building it. Most Java developers use Spring every day — @Component, @Autowired, @Transactional — without ever understanding what's happening underneath. The answer to all of it is one API: Java Reflection. In this series, we use Reflection as the lens AND the tool. Every concept we cover, we immediately apply to build a real piece of the framework. Theory and implementation, side by side. By the end, you won't just know how Reflection works. You'll know how frameworks think. Second blog is live now 👇
To view or add a comment, sign in
-
Setting every JPA relationship to FetchType.LAZY is the easy part. Living with the consequences is where most projects quietly fall apart. Here is what happens. You mark all your @ManyToOne and @OneToOne relationships as LAZY because every blog post tells you to. Your entities look clean. Then you write a service method that loads a Transaction and accesses transaction.getWorkspace().getName(). If the persistence context is still open, Hibernate silently fires a second query. If it is closed - which it will be once you disable OSIV like you should - you get a LazyInitializationException. The knee-jerk fix is to flip back to EAGER. Now every query that touches Transaction loads the Workspace too, whether the caller needs it or not. You just traded one problem for a worse one that is harder to detect. The actual solution is @EntityGraph on the repository method that needs the association: @EntityGraph(attributePaths = {"workspace", "createdByUser"}) List findByWorkspaceIdAndDateBetween(...) This tells Hibernate: for this specific query, load workspace and createdByUser in a single JOIN. Every other method on the same repository keeps lazy loading. You get per-method fetch control without touching the entity definition. The pattern I follow: entities are always LAZY. The repository method decides what to load based on the use case it serves. If a method does not access a relationship, it pays zero cost for it. If it does, the @EntityGraph makes it explicit and testable. To verify it works, I clear the persistence context in tests (entityManager.clear()), then access the relationship on the detached entity. If @EntityGraph did its job, no exception. If it did not, LazyInitializationException tells me exactly what I missed. Lazy-by-default is not a strategy. Lazy-by-default with explicit entity graphs per use case is. #SpringBoot #JPA #Hibernate #BackendDevelopment
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
-
-
Lazy vs Eager Loading — The N+1 Problem Every Java Dev Must Know One of the most common performance killers in Spring Data JPA is the infamous N+1 query problem — and it all starts with how you configure your fetch strategy. By default, @OneToMany and @ManyToMany use LAZY loading — related data is fetched only when accessed. Meanwhile, @ManyToOne and @OneToOne default to EAGER — data is loaded immediately with the parent. The trap? When you load a list of 100 customers and then access their orders in a loop: List<Customer> customers = customerRepo.findAll(); // 1 query for (Customer c : customers) { c.getOrders().size(); // 100 more queries! } // Total: 101 SQL queries = performance disaster Solutions that actually work: // 1. JOIN FETCH in JPQL @Query("SELECT c FROM Customer c JOIN FETCH c.orders") List<Customer> findAllWithOrders(); // 2. @EntityGraph @EntityGraph(attributePaths = {"orders"}) List<Customer> findAll(); Rule of thumb: ✅ Keep FetchType.LAZY as default ✅ Use JOIN FETCH or @EntityGraph when you know you need related data ✅ Enable Hibernate SQL logging to detect N+1 early ❌ Never switch everything to EAGER — that's trading N+1 for over-fetching #Java #SpringBoot #BackendDevelopment #SpringDataJPA #Performance #LearningInPublic
To view or add a comment, sign in
-
-
Most developers equate slow APIs with bad code. However, the issue often lies elsewhere. Consider this scenario: You have a query that appears perfectly fine: SELECT o.id, c.name FROM orders o JOIN customers c ON o.customer_id = c.id Yet, the API is painfully slow. Upon checking the execution plan, you find: NESTED LOOP → TABLE ACCESS FULL ORDERS → INDEX SCAN CUSTOMERS At first glance, this seems acceptable. But here's the reality: for each row in orders, the database is scanning and filtering again. If orders contain 1 million rows, that's 1 million loops. The real issue wasn’t the JOIN; it was the database's execution method. After adding an index: CREATE INDEX idx_orders_date ON orders(created_at); The execution plan changed to: INDEX RANGE SCAN ORDERS → INDEX SCAN CUSTOMERS As a result, query time dropped significantly. Key lessons learned include: • Nested Loop is efficient only when: → the outer table is small → the inner table is indexed • Hash Join is preferable when: → both tables are large → there are no useful indexes • Common performance issues stem from: → full table scans → incorrect join order → missing indexes → outdated statistics A common mistake is this Java code: for (Order o : orders) { o.getCustomer(); } This essentially creates a nested loop at the application level (N+1 query problem). Final takeaway: Don’t just write queries; understand how the database executes them. That's where true performance improvements occur. If you've resolved a slow query using execution plans, sharing your experience would be valuable. #BackendDevelopment #DatabaseOptimization #SQLPerformance #QueryOptimization #SystemDesign #SoftwareEngineering #Java #SpringBoot #APIPerformance #TechLearning #Developers #Coding #PerformanceTuning #Scalability #DistributedSystems #DataEngineering #Debugging #TechTips #LearnInPublic #EngineeringLife
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
Nice summary. These two annotations look similar at first, but they serve very different purposes. PathVariable is about addressing a specific resource, RequestParam is about shaping the response. Clean APIs start with understanding this difference.