Spring Interview Playbook

   


1️⃣ Core Spring


What is Spring Framework?

Answer:

  • Lightweight, open-source Java framework for enterprise applications

  • Based on IoC (Inversion of Control) and DI (Dependency Injection)

  • Promotes loose coupling and testability

  • Modular architecture (Core, AOP, JDBC, ORM, MVC, Security)

  • Eliminates heavy XML configuration (supports annotations & Java config)

Real-time example:

  • In a banking app → Service layer depends on Repository

  • Spring injects repository into service automatically


What is Inversion of Control (IoC)?

Answer:

  • Control of object creation is given to Spring container

  • Developer no longer uses new keyword for dependencies

  • Container manages:

    • Bean creation

    • Dependency wiring

    • Lifecycle

    • Configuration

Without IoC:

UserService service = new UserService();

With IoC:

@Autowired
UserService service;

Real-time example:

  • Large e-commerce app → 200+ services

  • IoC avoids manual object creation chaos


What is Dependency Injection (DI)?

Answer:

  • Technique to inject required dependencies into a class

  • Achieves loose coupling

  • Makes unit testing easier

Types of DI

  • Constructor Injection (Recommended)

  • Setter Injection

  • Field Injection (Avoid in production)

Why Constructor Injection?

  • Makes dependencies mandatory

  • Supports immutability

  • Easy for unit testing (Mockito)

Example:

@Service
class OrderService {
private final PaymentService paymentService;

public OrderService(PaymentService paymentService) {
this.paymentService = paymentService;
}
}

Real-time example:

  • OrderService depends on PaymentService

  • Spring injects automatically


What is a Spring Bean?

Answer:

  • Any object managed by Spring IoC container

  • Created, configured, and destroyed by container

Ways to define beans

  • @Component

  • @Service

  • @Repository

  • @Controller

  • @Bean (Java config)

  • XML configuration (legacy)

Real-time example:

  • UserService

  • EmailService

  • ProductRepository


What is Spring Bean Scopes?

Spring defines lifecycle and visibility of beans.

1. Singleton (Default)

  • One instance per Spring container

  • Shared across entire application

  • Thread-safe design required

Used in:

  • Service layer

  • DAO layer

  • Utility classes

Example:

@Scope("singleton")
@Service
class UserService {}

Real-time:

  • PaymentService shared by all users


2. Prototype

  • New object every time requested

  • Spring manages creation only (not destruction)

  • Suitable for stateful objects

Used in:

  • Report generator

  • Temporary calculation objects

@Scope("prototype")
@Component
class ReportBuilder {}

3. Request Scope (Web Apps)

  • One bean per HTTP request

  • Destroyed after request completes

Used in:

  • Request-specific form data

  • API request context


4. Session Scope

  • One bean per HTTP session

  • Lives until session expires

Used in:

  • Shopping cart

  • Logged-in user details


5. Application Scope

  • One per ServletContext

  • Shared across entire web application

Used in:

  • Application cache

  • Global settings


6. WebSocket Scope

  • One bean per WebSocket session

  • Used in chat applications


Scope Interview Follow-up Points

  • Singleton is NOT same as GoF Singleton

  • Singleton beans must be stateless

  • Prototype injected into Singleton → creates problem (use ObjectFactory)


What is @Component, @Service, @Repository, @Controller?

Answer:

All are stereotype annotations.

  • @Component → Generic bean

  • @Service → Business logic

  • @Repository → DAO (adds exception translation)

  • @Controller → MVC controller

Real-time:

  • Layered architecture separation


What is @Autowired?

Answer:

  • Automatically injects dependency

  • Works on constructor, setter, field

  • By default injects by type

  • Use @Qualifier if multiple beans

Example:

@Autowired
@Qualifier("stripePayment")
PaymentService paymentService;

What is Spring AOP?

Answer:

Aspect-Oriented Programming separates cross-cutting concerns.

Cross-cutting concerns:

  • Logging

  • Security

  • Transaction management

  • Monitoring

Key Terms:

  • Aspect → LoggingAspect

  • Advice → Before, After, Around

  • JoinPoint → Method execution

  • Pointcut → Expression

Example:

@Aspect
@Component
class LoggingAspect {
@Before("execution(* com.app.service.*.*(..))")
public void log() {
System.out.println("Method called");
}
}

Real-time:

  • Logging every service method without modifying code


What is Bean Lifecycle?

Phases:

  1. Bean instantiation

  2. Dependency injection

  3. @PostConstruct

  4. Ready for use

  5. @PreDestroy

  6. Destroy

Customization:

  • InitializingBean

  • DisposableBean

Real-time:

  • Opening DB connection on init

  • Closing resources on destroy


What is BeanFactory vs ApplicationContext?

Both are Spring IoC containers, but ApplicationContext is a more advanced version of BeanFactory.


BeanFactory

  • Basic IoC container

  • Responsible for:

    • Bean creation

    • Dependency injection

  • Beans loaded lazily (created only when requested)

  • Does NOT support:

    • Automatic AOP integration

    • Event publishing

    • Internationalization (i18n)

  • Lightweight and minimal

Example

BeanFactory factory =
new XmlBeanFactory(new ClassPathResource("beans.xml"));

MyService service = factory.getBean(MyService.class);

Used rarely in modern applications.


ApplicationContext

  • Advanced container (extends BeanFactory)

  • Provides all BeanFactory features +

    • AOP support

    • Event handling

    • Internationalization (MessageSource)

    • Environment & profiles

    • Annotation-based configuration

  • Beans loaded eagerly by default (singleton beans at startup)

  • Fully integrated with Spring Boot

Example

ApplicationContext context =
new AnnotationConfigApplicationContext(AppConfig.class);

MyService service = context.getBean(MyService.class);

Comparison Table

BeanFactoryApplicationContext
Basic IoC containerAdvanced container
Lazy loadingEager loading (default)
No built-in AOPSupports AOP
No event systemSupports events
Minimal featuresEnterprise-ready features

Real-Time Usage

  • ApplicationContext is used in almost all real-world applications.

  • Spring Boot automatically creates an ApplicationContext.

  • BeanFactory is mostly for:

    • Memory-constrained environments

    • Understanding core IoC concepts


Summary

BeanFactory is the basic container with lazy loading.
ApplicationContext extends BeanFactory and adds enterprise features like AOP, events, profiles, and is used in almost all real applications.


What is @Configuration and @Bean?

Answer:

  • @Configuration → Marks config class

  • @Bean → Defines custom bean

Example:

@Configuration
class AppConfig {

@Bean
public ModelMapper modelMapper() {
return new ModelMapper();
}
}

Real-time:

  • Third-party libraries as beans


What is Circular Dependency?

Answer:

A circular dependency occurs when:

  • Bean A depends on Bean B

  • Bean B depends on Bean A

This creates a dependency cycle.


Example (Constructor Injection – Fails)

@Service
class A {
private final B b;

public A(B b) {
this.b = b;
}
}

@Service
class B {
private final A a;

public B(A a) {
this.a = a;
}
}

Result:

  • Spring tries to create A → needs B

  • To create B → needs A

  • Fails with BeanCurrentlyInCreationException


Setter Injection – Works (Not Recommended)

@Service
class A {
private B b;

@Autowired
public void setB(B b) {
this.b = b;
}
}

@Service
class B {
private A a;

@Autowired
public void setA(A a) {
this.a = a;
}
}

Why it works:

  • Spring first creates beans without dependencies

  • Injects dependencies afterward

  • Breaks creation cycle

Why not recommended:

  • Hides poor design

  • Allows partially initialized beans

  • Encourages tight coupling

  • Makes dependencies optional (not enforced)


Proper Solution (Refactor Design)

Instead of A and B depending on each other, extract common logic into a third service.

Refactored Design

@Service
class CommonService {
}

@Service
class A {
private final CommonService commonService;

public A(CommonService commonService) {
this.commonService = commonService;
}
}

@Service
class B {
private final CommonService commonService;

public B(CommonService commonService) {
this.commonService = commonService;
}
}

Now:

  • A → CommonService

  • B → CommonService

  • No circular dependency


Interview Summary

  • Circular dependency = two beans depend on each other

  • Constructor injection fails

  • Setter injection works but is bad design

  • Best solution → redesign architecture and remove tight coupling


What is Profiles in Spring?

Answer:

  • Used for environment-specific configuration

  • Allows different beans and properties to be loaded based on the active environment

  • Helps separate configuration without changing code

  • Common real-time environment names:

    • local

    • dev

    • qa

    • uat

    • staging

    • prod

Example Using @Profile

@Profile("dev")
@Component
class DevDataSource {
}

@Profile("prod")
@Component
class ProdDataSource {
}

Only the bean matching the active profile will be loaded.

How to Activate Profile

In application.properties

spring.profiles.active=dev

Or via command line

--spring.profiles.active=prod

Profile-Specific Property Files

  • application-local.properties

  • application-dev.properties

  • application-qa.properties

  • application-uat.properties

  • application-staging.properties

  • application-prod.properties

Spring automatically loads the correct file based on the active profile.

Real-Time Example

  • local → Developer machine DB

  • dev → Shared development database

  • qa → QA testing database

  • uat → User acceptance testing environment

  • staging → Pre-production environment

  • prod → Production database

Interview Summary

Profiles allow loading environment-specific beans and configurations such as database URLs, logging levels, API keys, and feature flags without modifying application code.


What is @Value and @PropertySource?

Answer:

  • Used to inject values from properties files

  • @Value → Injects a specific property value

  • @PropertySource → Loads external/custom property files into Spring context

Example using @Value

@Value("${server.port}")
private int port;

Injecting custom property:

@Value("${app.name}")
private String appName;

Example using @PropertySource

@Configuration
@PropertySource("classpath:custom.properties")
class AppConfig {
}

This loads custom.properties so values can be injected using @Value.


Used In

  • Database configuration

  • API keys

  • External service URLs

  • Feature flags

Interview Summary

@Value is used to inject individual property values, while @PropertySource is used to load additional properties files into the Spring application context.


What is Environment Abstraction?

Answer:

  • Provides access to application properties

  • Gives access to active profiles

  • Allows reading system environment variables

  • Supports checking default profiles

  • Helps implement environment-based logic

Spring provides the Environment interface for this.


Example using Environment

@Autowired
private Environment env;

Read property

String dbUrl = env.getProperty("spring.datasource.url");

Get active profiles

String[] profiles = env.getActiveProfiles();

Get default profiles

String[] defaultProfiles = env.getDefaultProfiles();

Read system environment variable

String javaHome = env.getProperty("JAVA_HOME");

Check if profile is active

if (env.acceptsProfiles("prod")) {
System.out.println("Production environment");
}

Used In

  • Dynamic configuration access

  • Profile-based conditional logic

  • Reading OS environment variables

  • Feature toggles based on environment


Interview Summary

Environment abstraction allows accessing properties, profiles, and system variables programmatically using the Environment interface, enabling environment-aware application behavior.


What is Lazy Initialization?

Answer:

  • @Lazy → Bean is created only when it is first requested

  • Default singleton beans are created eagerly at startup

  • Helps reduce application startup time

  • Useful for heavy or rarely used beans

Example using @Lazy

@Lazy
@Service
class HeavyService {
}

Bean will be created only when it is first injected or accessed.

Using @Lazy on Injection

@Service
class OrderService {

private final HeavyService heavyService;

public OrderService(@Lazy HeavyService heavyService) {
this.heavyService = heavyService;
}
}

Here, HeavyService is initialized only when actually used.

Used In

  • Expensive initialization logic

  • Large configuration objects

  • Rarely used services

  • Improving startup performance

Interview Summary

Lazy initialization delays bean creation until it is needed, helping optimize startup time and resource usage.


What is difference between @Primary and @Qualifier?

Answer:

  • @Primary → Marks a bean as the default choice when multiple beans of the same type exist

  • @Qualifier → Explicitly specifies which bean to inject

Used when multiple implementations of the same interface are present.

Example Scenario

public interface PaymentService {
void pay();
}

Two Implementations

@Service
@Primary
class StripePaymentService implements PaymentService {
public void pay() {}
}

@Service
class PaypalPaymentService implements PaymentService {
public void pay() {}
}

Injection Without Qualifier

@Autowired
private PaymentService paymentService;

Here, StripePaymentService will be injected because it is marked with @Primary.

Using @Qualifier

@Autowired
@Qualifier("paypalPaymentService")
private PaymentService paymentService;

Here, PaypalPaymentService will be injected explicitly.


When to Use

  • @Primary → When one implementation should act as default

  • @Qualifier → When you need specific implementation


Interview Summary

@Primary defines the default bean among multiple candidates, while @Qualifier allows explicit selection of a specific bean during injection.


What is @Conditional annotation?

Answer:

  • Creates a bean only if a specific condition is satisfied

  • Used heavily in Spring Boot auto-configuration

  • Enables conditional bean registration

  • Helps build flexible and modular configuration

Common Conditional Annotations

  • @ConditionalOnProperty → Loads bean if property exists or has specific value

  • @ConditionalOnClass → Loads bean if a class is present in classpath

  • @ConditionalOnMissingBean → Loads bean only if no other bean of same type exists

  • @ConditionalOnBean → Loads bean only if another bean exists

Example using @ConditionalOnProperty

@Configuration
class FeatureConfig {

@Bean
@ConditionalOnProperty(name = "feature.enabled", havingValue = "true")
public FeatureService featureService() {
return new FeatureService();
}
}

application.properties:

feature.enabled=true

Bean loads only if property is true.

Example using @ConditionalOnClass

@Configuration
@ConditionalOnClass(name = "com.mysql.cj.jdbc.Driver")
class MySqlConfig {
}

Loads only if MySQL driver is available.


Used For

  • Feature toggling

  • Optional modules

  • Auto-configuration logic

  • Environment-based bean loading

Interview Summary

@Conditional annotations allow beans to be created only when certain conditions are met, widely used in Spring Boot’s auto-configuration and feature toggling.


Common Core Spring Interview Scenarios.

What are the thread-safety concerns with Singleton beans and how to keep them stateless?

  • Singleton beans are shared across multiple threads and are not thread-safe by default.

  • Problem occurs when mutable instance variables are used.
    Bad example:

@Service
class CounterService {
private int count = 0;
public void increment() { count++; }
}

This causes race conditions.
Correct (stateless) example:

@Service
class CounterService {
public int increment(int count) { return count + 1; }
}

Here no shared mutable state exists, making it thread-safe.


What happens when a Prototype bean is injected into a Singleton bean?

  • Prototype bean is created only once during injection.

  • Same instance reused inside singleton.

Solution 1: Using ObjectProvider
    @Service
    class A {
    @Autowired
    private ObjectProvider<B> provider;
    public void useB() {
    B b = provider.getObject();
    }
    }

    Solution 2: Using Provider (JSR-330)

    @Service
    class A {
    @Autowired
    private javax.inject.Provider<B> provider;
    public void useB() {
    B b = provider.get();
    }
    }

    Solution 3: Using @Lookup method injection

    @Service
    abstract class A {
    public void useB() {
    B b = getB();
    }
    @Lookup
    protected abstract B getB();
    }

    Each call returns a new prototype instance.


    Why is constructor injection preferred?

    • Makes dependencies mandatory.

    • Supports immutability.

    • Easier for unit testing.

    • Detects circular dependency early.


    What is the difference between @Component and @Bean?

    @Component

    • Auto-detected through component scanning (@ComponentScan)

    • Used for application-level classes like @Service@Repository@Controller

    • Spring automatically instantiates and manages the bean

    • Best for classes you own and can annotate

    @Bean

    • Declared inside a @Configuration class

    • Used for third-party classes or when you cannot modify the source code

    • Provides fine-grained control — you explicitly define how the object is created, configured, initialized, and customized before registering it as a Spring bean

    Example

    @Configuration
    class AppConfig {

    @Bean
    public ObjectMapper objectMapper() {
    ObjectMapper mapper = new ObjectMapper();
    mapper.findAndRegisterModules();
    return mapper;
    }
    }

    Interview Summary

    Use @Component for your own classes.
    Use @Bean when you need manual control or for external libraries.


    What are proxies and how does Spring create proxies for AOP?

    Answer:

    • A proxy is a wrapper object created by Spring around your actual bean.

    • It intercepts method calls and adds extra behavior like:

      • Transactions

      • Logging

      • Security

      • Caching

    The original object is called the target, and Spring returns the proxy instead of the real object.


    How Spring Creates Proxies

    Spring uses two mechanisms:

    • JDK Dynamic Proxy → Used when the class implements an interface

    • CGLIB (Code Generation Library) → Used when no interface is present (creates subclass at runtime)

    You can force CGLIB:

    spring.aop.proxy-target-class=true

    Proxy Flow

    Client → Proxy → (Advice Applied) → Target Method

    Example with @Transactional:

    @Transactional
    public void transfer() {
    // business logic
    }

    Flow:

    1. Client calls transfer()

    2. Proxy starts transaction

    3. Target method executes

    4. Proxy commits or rolls back

    Simple Interview Definition

    Spring creates proxy objects around beans to intercept method calls and apply cross-cutting concerns like transactions and logging using JDK dynamic proxies or CGLIB.


    How does @Transactional work internally?

    • Spring creates a proxy around the bean.

    • When method is called, proxy:

      • Starts transaction.

      • Executes method.

      • Commits if successful.

      • Rolls back if RuntimeException occurs.
        Simple flow:
        Call method → Proxy starts transaction → Business logic runs → Commit/Rollback.


    What happens if @Transactional is missing?

    • No transaction boundary.

    • Partial updates possible.

    • Risk of inconsistent database state.


    Interview Summary

    These topics test understanding of Spring internals like proxy mechanism, transaction flow, dependency injection behavior, thread safety, and real-world production design practices.


    Core Spring Summary

    Core Spring focuses on:

    • IoC container

    • Dependency Injection

    • Bean lifecycle

    • AOP

    • Scopes

    • Configuration management

    • Environment abstraction




     


    2️⃣ Spring MVC 


    What is Spring MVC?

    Answer:

    • A web framework based on Model-View-Controller pattern

    • Built on top of Spring Core

    • Used to build web applications and REST APIs

    • Handles HTTP requests and responses

    MVC Components:

    • Model → Data (DTO, Entity)

    • View → UI (JSP, Thymeleaf) or JSON

    • Controller → Handles requests

    Real-time example:

    • E-commerce site

      • Controller → Handles /products

      • Service → Fetches products

      • View → Displays products page or JSON


    What is DispatcherServlet?

    Answer:

    • Front Controller in Spring MVC

    • Handles all incoming HTTP requests

    • Delegates to appropriate controller

    Flow:

    1. Client sends request

    2. DispatcherServlet receives

    3. Finds handler using HandlerMapping

    4. Calls controller

    5. Returns response

    Real-time example:

    • All API calls like /login/users/orders go through DispatcherServlet


    What is @Controller?

    Answer:

    • Marks a class as MVC Controller

    • Returns View name by default

    • Used in traditional MVC apps

    @Controller
    public class HomeController {

    @GetMapping("/home")
    public String home() {
    return "home"; // home.jsp
    }
    }

    What is @RestController?

    Answer:

    • Combination of:

      • @Controller

      • @ResponseBody

    • Returns JSON/XML instead of View

    @RestController
    public class UserController {

    @GetMapping("/users")
    public List<User> getUsers() {
    return userService.getAll();
    }
    }

    Real-time example:

    • Microservices returning JSON responses


    Difference between @Controller and @RestController?

    @Controller@RestController
    Returns View name (JSP/Thymeleaf)Returns JSON or XML directly
    Used in traditional MVC appsUsed in REST APIs / Microservices
    Needs @ResponseBody for JSON@ResponseBody applied automatically
    Mostly used in monolithic web appsCommon in distributed systems / SOA / Microservices

    Example using @Controller

    @Controller
    public class HomeController {

    @GetMapping("/home")
    public String home() {
    return "home"; // resolves to home.jsp or home.html
    }
    }

    Returns a view name, not JSON.

    Example using @RestController

    @RestController
    public class UserController {

    @GetMapping("/users")
    public List<String> getUsers() {
    return List.of("A", "B");
    }
    }

    Returns JSON response directly.

    Key Point

    @RestController = @Controller + @ResponseBody

    Interview Summary

    Use @Controller for server-side rendered web applications.
    Use @RestController for REST APIs, distributed environments, SOA, and microservices where JSON/XML responses are required.


    What is @RequestMapping?

    • Used to map HTTP requests to controller methods

    • Can be applied at class level and method level

    • Defines URL path and HTTP method

    Common variants:

    • @GetMapping

    • @PostMapping

    • @PutMapping

    • @DeleteMapping

    • @PatchMapping

    Example – Class Level Mapping

    @RestController
    @RequestMapping("/api")
    class UserController {
    }

    Base URL becomes: /api

    Example – Method Level Mapping

    @RestController
    class UserController {

    @GetMapping("/users/{id}")
    public User getUser(@PathVariable Long id) {
    return new User(id, "John");
    }
    }

    URL becomes: /users/{id}

    Example – Class + Method Level Combined

    @RestController
    @RequestMapping("/api")
    class UserController {

    @GetMapping("/users/{id}")
    public User getUser(@PathVariable Long id) {
    return new User(id, "John");
    }
    }

    Final URL: /api/users/{id}

    Interview Summary: @RequestMapping maps a URL and HTTP method to a specific controller method in Spring MVC or REST APIs.


    What is @PathVariable?

    • Extracts value from the URL path

    • Binds URI template variable to method parameter

    • Used to identify specific resource

    Example request:
    GET /users/10

    Example code:

    @GetMapping("/users/{id}")
    public User get(@PathVariable Long id) {
    return new User(id, "John");
    }

    Used for:

    • Resource identification

    • RESTful APIs

    • Accessing specific entity by ID

    Interview Summary: @PathVariable is used to capture dynamic values from the URL path and bind them to method parameters.


    What is @RequestParam?

    • Extracts query parameter from URL

    • Binds request parameter to method argument

    • Used for optional or additional data

    Example request:
    GET /users?id=10

    Example code:

    @GetMapping("/users")
    public User get(@RequestParam Long id) {
    return new User(id, "John");
    }

    Used for:

    • Filtering

    • Pagination

    • Sorting

    • Optional parameters

    Interview Summary: @RequestParam is used to capture query parameters from the URL and bind them to controller method parameters.


    What is @RequestBody?

    • Maps HTTP request body to a Java object

    • Converts JSON/XML into Java object using HttpMessageConverter (Jackson by default)

    • Commonly used in POST and PUT APIs

    Example:

    @PostMapping("/users")
    public User create(@RequestBody User user) {
    return user;
    }

    Example JSON request body:

    {
    "id": 1,
    "name": "John"
    }

    Real-time usage:

    • Creating a new user via JSON payload

    • Updating existing records

    • Sending complex request data from frontend

    Interview Summary: @RequestBody binds incoming JSON/XML request data to a Java object in REST APIs.


    What is @ResponseBody?

    • Converts the return value of a method into JSON or XML

    • Uses HttpMessageConverters (Jackson by default for JSON)

    • Writes response directly to HTTP response body instead of returning a view

    • Automatically included when using @RestController

    Example:

    @Controller
    public class UserController {

    @GetMapping("/users")
    @ResponseBody
    public User getUser() {
    return new User(1L, "John");
    }
    }

    Interview Summary: @ResponseBody tells Spring to serialize the returned object into JSON/XML and send it directly in the HTTP response.


    What is HttpMessageConverter?

    • Converts Java object → JSON/XML

    • Converts JSON/XML → Java object

    • Works between HTTP request/response and controller methods

    • Uses Jackson library by default for JSON

    Example:

    @GetMapping("/users")
    public User getUser() {
    return new User(1L, "John");
    }

    Spring automatically converts the User object into JSON in the HTTP response.

    For request body:

    @PostMapping("/users")
    public User create(@RequestBody User user) {
    return user;
    }

    Spring converts incoming JSON into a User object.

    Real-time usage:

    • Automatically serializes objects to JSON in REST APIs

    • Converts frontend JSON payload into Java objects

    Interview Summary: HttpMessageConverter interface handles automatic conversion between Java objects and HTTP request/response formats like JSON or XML.


    What is ResponseEntity?

    • A Spring class used to represent the entire HTTP response

    • Allows control over:

      • HTTP status code

      • Response headers

      • Response body

    • Mainly used in REST APIs

    • It is a class in Spring (org.springframework.http.ResponseEntity)


    Example – Return with Status 200

    @GetMapping("/users/{id}")
    public ResponseEntity<User> getUser(@PathVariable Long id) {
    User user = new User(id, "John");
    return ResponseEntity.ok(user);
    }

    Example – Return Custom Status

    @PostMapping("/users")
    public ResponseEntity<User> createUser(@RequestBody User user) {
    return ResponseEntity
    .status(HttpStatus.CREATED)
    .body(user);
    }

    Returns → HTTP 201 Created


    Example – Return Custom Header

    @GetMapping("/users")
    public ResponseEntity<User> getUser() {
    User user = new User(1L, "John");
    return ResponseEntity
    .ok()
    .header("X-App-Version", "1.0")
    .body(user);
    }

    Response includes custom header:
    X-App-Version: 1.0


    Example – Return Only Status

    @DeleteMapping("/users/{id}")
    public ResponseEntity<Void> deleteUser(@PathVariable Long id) {
    return ResponseEntity.noContent().build();
    }

    Returns → HTTP 204 No Content


    Interview Summary

    ResponseEntity gives full control over HTTP response including body, headers, and status code, making it ideal for building proper REST APIs.


    What is Model, ModelMap, and ModelAndView?

    • Used in traditional Spring MVC (server-side rendering)

    • Used to pass data from controller to view (JSP/Thymeleaf)

    Model

    • Stores data for the view

    • Simple interface

    model.addAttribute("name", "Siraj");

    ModelMap

    • Similar to Model

    • Backed by a Map structure

    • Allows key-value storage

    modelMap.addAttribute("name", "Siraj");

    ModelAndView

    • Combines model data + view name

    • Returns both in single object

    return new ModelAndView("home", "name", "Siraj");

    Used in:

    • Traditional MVC applications (JSP, Thymeleaf)

    Interview Summary: Model and ModelMap store data for the view, while ModelAndView holds both the model data and view name together.


    What is ViewResolver?

    • Resolves logical view name to actual view file

    • Used in traditional Spring MVC (not REST)

    • Maps returned String from controller to physical view

    Example:
    Controller returns:

    return "home";

    Resolved to:
    /WEB-INF/views/home.jsp

    Common ViewResolvers

    • InternalResourceViewResolver → For JSP

    • ThymeleafViewResolver → For Thymeleaf templates

    Interview Summary

    ViewResolver converts the logical view name returned by a controller into the actual view file path in traditional Spring MVC applications.


    What is Exception Handling in Spring MVC?

    Spring provides two main ways to handle exceptions: @ExceptionHandler and @ControllerAdvice.


    What is @ExceptionHandler?

    • Used inside a controller

    • Handles specific exceptions for that controller only

    • Suitable for controller-specific logic

    Example:

    @RestController
    class UserController {

    @GetMapping("/users/{id}")
    public User getUser(@PathVariable Long id) {
    throw new UserNotFoundException();
    }

    @ExceptionHandler(UserNotFoundException.class)
    public ResponseEntity<String> handle(UserNotFoundException ex) {
    return ResponseEntity.status(HttpStatus.NOT_FOUND)
    .body("User not found");
    }
    }

    Scope → Only applies to UserController.


    What is @ControllerAdvice?

    • Global exception handler

    • Applies to all controllers

    • Used for centralized error handling

    • Keeps controllers clean

    Example:

    @ControllerAdvice
    public class GlobalExceptionHandler {

    @ExceptionHandler(UserNotFoundException.class)
    public ResponseEntity<String> handle(UserNotFoundException ex) {
    return ResponseEntity.status(HttpStatus.NOT_FOUND)
    .body("User not found");
    }
    }

    Scope → Applies to all controllers in the application.

    Key Differences

    @ExceptionHandler@ControllerAdvice
    Local to one controllerGlobal across application
    Defined inside controllerDefined in separate class
    Used for specific casesUsed for centralized error handling
    Harder to manage if many controllersClean and scalable approach

    Real-Time Example

    • Return 404 when user not found

    • Return 400 for validation errors

    • Return 500 for unexpected server errors


    Interview Summary

    @ExceptionHandler handles exceptions at controller level, while @ControllerAdvice provides centralized global exception handling for the entire application.


    Difference between @RestControllerAdvice and @ControllerAdvice?

    • Both are used for global exception handling

    • Both apply across multiple controllers

    @ControllerAdvice

    • Used in traditional Spring MVC applications

    • Typically returns view names (JSP, Thymeleaf)

    • Requires @ResponseBody if returning JSON

    Example:

    @ControllerAdvice
    public class GlobalHandler {

    @ExceptionHandler(Exception.class)
    public String handle() {
    return "error"; // returns error.jsp
    }
    }


    @RestControllerAdvice

    • Used in REST APIs

    • Returns JSON/XML by default

    • Combines @ControllerAdvice + @ResponseBody

    Example:

    @RestControllerAdvice
    public class GlobalHandler {

    @ExceptionHandler(Exception.class)
    public String handle() {
    return "Something went wrong";
    }
    }

    Returns JSON response automatically.


    Interview Summary

    @ControllerAdvice is used for global exception handling in MVC apps (view-based), while @RestControllerAdvice is used in REST APIs and automatically returns JSON responses.


    What is Validation in Spring MVC?

    • Used to validate incoming request data

    • Ensures data integrity before processing

    • Works with Bean Validation (Jakarta Validation / Hibernate Validator)

    Common annotations:

    • @Valid → Triggers validation

    • @NotNull → Field must not be null

    • @Size → Restricts length

    • @Email → Valid email format


    Example – Entity Validation

    public class User {

    @NotNull
    @Size(min = 3, max = 20)
    private String name;

    @Email
    private String email;
    }

    Example – Controller Validation

    @PostMapping("/users")
    public User create(@Valid @RequestBody User user) {
    return user;
    }

    If validation fails → Spring returns HTTP 400 (Bad Request).

    Real-Time Usage

    • Validate registration form

    • Validate login request

    • Validate API payload before saving to DB


    Interview Summary

    Validation in Spring MVC ensures incoming request data meets defined constraints using annotations like @NotNull@Size, and @Email, triggered by @Valid.


    What is CORS in Spring MVC?

    • CORS stands for Cross-Origin Resource Sharing

    • Allows frontend applications hosted on different domain/port to access backend APIs

    • Required when frontend and backend run on different origins

    Example:

    @CrossOrigin(origins = "http://localhost:3000")
    @GetMapping("/users")
    public List<User> getUsers() {
    return List.of(new User(1L, "John"));
    }

    Allows requests from http://localhost:3000.


    Global CORS Configuration

    @Configuration
    public class WebConfig implements WebMvcConfigurer {

    @Override
    public void addCorsMappings(CorsRegistry registry) {
    registry.addMapping("/**")
    .allowedOrigins("http://localhost:3000")
    .allowedMethods("GET", "POST", "PUT", "DELETE");
    }
    }

    Real-Time Usage

    • React app calling Spring Boot backend

    • Angular frontend hosted on different server

    • Microservices communicating across domains


    Interview Summary

    CORS allows cross-origin requests between frontend and backend applications, typically enabled using @CrossOrigin or global configuration in Spring MVC.


      What is Interceptor?

      • Intercepts HTTP request before and after controller execution

      • Spring-specific mechanism

      • Works after DispatcherServlet

      • Similar to Servlet Filter but more controller-focused

      Used for:

      • Logging

      • Authentication checks

      • Authorization

      • Performance timing

      • Pre/Post request processing

      Example – Creating Interceptor

      public class LoggingInterceptor implements HandlerInterceptor {

      @Override
      public boolean preHandle(HttpServletRequest request,
      HttpServletResponse response,
      Object handler) {
      System.out.println("Request received: " + request.getRequestURI());
      return true; // continue request
      }
      }

      Registering Interceptor

      @Configuration
      public class WebConfig implements WebMvcConfigurer {

      @Override
      public void addInterceptors(InterceptorRegistry registry) {
      registry.addInterceptor(new LoggingInterceptor());
      }
      }

      Real-Time Usage

      • Log all API requests

      • Check authentication token

      • Measure request processing time

      Interview Summary

      An Interceptor in Spring MVC intercepts requests before and after controller execution, commonly used for logging, authentication, and performance monitoring.


      What is Filter vs Interceptor?

      FilterInterceptor
      Part of Servlet API (javax.servlet)Spring-specific (HandlerInterceptor)
      Executes before DispatcherServletExecutes after DispatcherServlet but before controller
      Configured at servlet container levelConfigured in Spring context
      Works for all requests (static + dynamic)Works only for controller requests
      Used for CORS, encoding, compressionUsed for authentication, logging, timing

      Example – Filter

      @Component
      public class LoggingFilter implements Filter {

      @Override
      public void doFilter(ServletRequest request,
      ServletResponse response,
      FilterChain chain) {
      System.out.println("Filter executed");
      chain.doFilter(request, response);
      }
      }

      Example – Interceptor

      public class LoggingInterceptor implements HandlerInterceptor {

      @Override
      public boolean preHandle(HttpServletRequest request,
      HttpServletResponse response,
      Object handler) {
      System.out.println("Interceptor executed");
      return true;
      }
      }

      Interview Summary

      Filter is a Servlet-level component that runs before Spring’s DispatcherServlet, while Interceptor is Spring-specific and runs after DispatcherServlet but before the controller, mainly used for authentication and logging.


      What is REST API Best Practice?

      • Use proper HTTP methods

        • GET → Read

        • POST → Create

        • PUT → Update

        • DELETE → Delete

      • Use plural nouns for resources

        • /users instead of /user

        • /orders instead of /getOrders

      • Use correct HTTP status codes

        • 200 → OK

        • 201 → Created

        • 400 → Bad Request

        • 404 → Not Found

        • 500 → Server Error

      • Keep APIs stateless

        • Do not store client session on server

        • Each request must contain required authentication info

      • Implement versioning

        • /api/v1/users

        • Prevents breaking changes

      • Use meaningful URLs

        • /users/10/orders

        • Avoid verbs in URL

      • Validate input properly

      • Secure APIs using HTTPS


      Interview Summary

      REST API best practices include using correct HTTP methods and status codes, plural resource naming, stateless design, proper versioning, and secure, clean URL structure.


        What is Content Negotiation?

        • Mechanism to decide the response format (JSON, XML, etc.)

        • Allows client to specify preferred response type

        • Commonly used in REST APIs

        Based on:

        • Accept header (most common)

        • URL extension (e.g., .json.xml)

        • Request parameter (optional configuration)

        Example – Using Accept Header

        Request:

        GET /users
        Accept: application/json

        Response:

        {
        "id": 1,
        "name": "John"
        }

        Request:

        GET /users
        Accept: application/xml

        Response:

        <User>
        <id>1</id>
        <name>John</name>
        </User>

        Same API → Different response formats based on client request.


        Example in Spring

        @GetMapping(value = "/users", produces = "application/json")
        public List<User> getUsers() {
        return List.of(new User(1L, "John"));
        }

        Spring automatically selects the correct format using HttpMessageConverter.


        Real-Time Usage

        • Same API supports JSON and XML clients

        • Public APIs serving multiple client types

        • Integration with legacy systems requiring XML


        Interview Summary

        Content negotiation allows the server to return data in different formats (JSON or XML) based on client request, usually determined by the Accept header.


          How to handle large file upload in spring?

          • Use MultipartFile to receive uploaded files

          • Configure maximum file size in application properties

          • Prefer streaming instead of loading entire file into memory

          • Validate file type and size before processing


          Configure Max File Size

          spring.servlet.multipart.max-file-size=50MB
          spring.servlet.multipart.max-request-size=50MB

          Example – Using MultipartFile

          @PostMapping("/upload")
          public String uploadFile(@RequestParam("file") MultipartFile file) throws IOException {
          System.out.println("File name: " + file.getOriginalFilename());
          return "File uploaded";
          }

          Streaming Large Files (Better for Big Files)

          @PostMapping("/upload")
          public String uploadFile(@RequestParam("file") MultipartFile file) throws IOException {
          try (InputStream inputStream = file.getInputStream()) {
          // process stream line by line
          }
          return "File processed";
          }

          Avoid:

          file.getBytes(); // Loads entire file into memory

          Real-Time Usage

          • Bulk CSV upload

          • Excel import

          • Data migration files

          • Media uploads


          Interview Summary

          Large file uploads in Spring are handled using MultipartFile, proper size configuration, and streaming to avoid memory issues.


          How to implement API versioning?

          API versioning allows you to support multiple versions of an API without breaking existing clients.

          Common Options

          • URL versioning → /api/v1/users

          • Header-based versioning

          • Media-type (Accept header) versioning

          1. URL Versioning (Most Common & Simple)

          @RestController
          @RequestMapping("/api/v1/users")
          class UserControllerV1 {
          }

          Next version:

          @RestController
          @RequestMapping("/api/v2/users")
          class UserControllerV2 {
          }

          Simple, clear, and easy to maintain.


          2. Header-Based Versioning

          Client sends custom header:

          X-API-VERSION: 1

          Controller:

          @GetMapping(value = "/users", headers = "X-API-VERSION=1")
          public String getUsersV1() {
          return "Version 1";
          }

          3. Media-Type Versioning

          Client sends:

          Accept: application/vnd.company.v1+json

          Controller:

          @GetMapping(value = "/users", produces = "application/vnd.company.v1+json")
          public String getUsersV1() {
          return "Version 1";
          }

          Best Practice

          • URL versioning is the simplest and most readable

          • Easy for clients and documentation

          • Widely used in real-world REST APIs


          Interview Summary

          API versioning can be implemented using URL, headers, or media type. URL versioning (/api/v1/...) is the most common and easiest approach in real projects.


          Why DTO vs Entity separation?

          • Avoid exposing internal DB model in APIs

          • Prevent lazy loading issues

          • Hide sensitive fields (e.g., password)

          • Decouple API layer from persistence layer

          • Improve security and flexibility

          Example (Good Practice):

          public class UserDTO {
          private Long id;
          private String name;
          }

          Interview Summary: Use DTOs to control what data is exposed and keep your API independent from the database structure.






          3️⃣ Spring Boot


          What is Spring Boot?

          Answer:

          • An opinionated framework built on top of Spring

          • Simplifies Spring application development

          • Eliminates heavy XML configuration

          • Provides production-ready features

          Key Features:

          • Auto-configuration

          • Embedded servers (Tomcat, Jetty, Undertow)

          • Starter dependencies

          • Actuator monitoring

          • Minimal setup

          Real-time example:

          • Build REST API in minutes without manually configuring DispatcherServlet


          Why Spring Boot Over Traditional Spring?

          Answer:

          • No manual configuration

          • No web.xml

          • Embedded server

          • Less boilerplate

          • Faster development

          Traditional Spring:

          • Configure XML

          • Setup server manually

          Spring Boot:

          • Just @SpringBootApplication

          • Run main method


          What is @SpringBootApplication?

          Answer:
          • Main annotation used to bootstrap a Spring Boot application

          • Combination of:

            • @Configuration → Marks class as configuration class

            • @EnableAutoConfiguration → Enables auto-configuration

            • @ComponentScan → Scans components in current package and sub-packages

          Example

          @SpringBootApplication
          public class App {
          public static void main(String[] args) {
          SpringApplication.run(App.class, args);
          }
          }

          What Happens Internally?

          • Starts embedded server (Tomcat by default)

          • Creates ApplicationContext

          • Scans components

          • Applies auto-configuration

          • Registers all beans

          Real-Time Usage

          • Entry point of Spring Boot application

          • Starts the entire application context

          • Used in microservices and standalone apps

          Interview Summary

          @SpringBootApplication is a convenience annotation that combines configuration, component scanning, and auto-configuration to start a Spring Boot application.


          What is Auto-Configuration?

          Answer:

          • Automatically configures Spring beans based on:

            • Classpath dependencies

            • Existing beans

            • Application properties

          • Reduces manual configuration

          • Enabled by @EnableAutoConfiguration (included in @SpringBootApplication)

          Common Conditional Annotations Used

          • @ConditionalOnClass → Configures bean if a class exists in classpath

          • @ConditionalOnMissingBean → Creates bean only if not already defined

          • @ConditionalOnProperty → Configures bean based on property value

          Example

          Add dependency:

          spring-boot-starter-data-jpa

          Spring Boot automatically configures:

          • DataSource

          • EntityManagerFactory

          • TransactionManager

          No manual configuration required.

          How It Works Internally

          • Boot checks classpath

          • Finds matching auto-config classes

          • Applies configuration if conditions match

          Real-Time Usage

          • Add dependency → Boot configures required infrastructure

          • Speeds up development

          • Eliminates XML configuration

          Interview Summary

          Auto-Configuration automatically sets up Spring beans based on dependencies, existing beans, and properties using conditional annotations, minimizing manual setup.


          How Does Auto-Configuration Work Internally?

          Answer:

          • Uses spring.factories (Spring Boot 2) or AutoConfiguration.imports (Spring Boot 3)

          • Loads auto-configuration classes at startup

          • Applies configuration conditionally

          • Creates beans only if conditions match

          Internal Flow

          1. @SpringBootApplication enables auto-configuration

          2. Spring Boot reads:

            • META-INF/spring.factories (Boot 2)

            • META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports (Boot 3)

          3. Loads listed auto-configuration classes

          4. Applies conditional annotations like:

            • @ConditionalOnClass

            • @ConditionalOnMissingBean

            • @ConditionalOnProperty

          5. Creates beans only if all conditions are satisfied


          What are Starter Dependencies in Spring Boot?

          Answer:

          • Predefined dependency bundles

          • Provide commonly used libraries together

          • Simplify project setup

          • Managed and version-aligned by Spring Boot

          Common Examples

          • spring-boot-starter-web → Spring MVC + Tomcat + Jackson

          • spring-boot-starter-data-jpa → Spring Data JPA + Hibernate

          • spring-boot-starter-security → Spring Security

          • spring-boot-starter-test → JUnit + Mockito + Test utilities

          • spring-boot-starter-actuator → Production monitoring endpoints

          Example (Maven)

          <dependency>
          <groupId>org.springframework.boot</groupId>
          <artifactId>spring-boot-starter-web</artifactId>
          </dependency>

          No need to manually add Tomcat or Jackson.

          Benefits

          • No dependency version conflicts

          • Less manual version management

          • Faster development setup

          • Production-ready defaults

          Interview Summary

          Starter dependencies are predefined dependency groups in Spring Boot that simplify configuration, reduce version conflicts, and speed up development.


            What is Embedded Server in Spring Boot?

            Answer:

            • Spring Boot includes an embedded web server inside the application

            • Default server → Embedded Tomcat

            • Other options → Jetty, Undertow

            • No need to deploy WAR file to external server

            How It Works

            Spring Boot packages application as a JAR with server included:

            <packaging>jar</packaging>

            Run using:

            java -jar app.jar

            Application starts with embedded server automatically.

            How to Change Server

            Example (Maven – Use Jetty instead of Tomcat):

            <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-jetty</artifactId>
            </dependency>

            Real-Time Usage

            • Microservices deployed independently

            • Docker container deployments

            • Cloud-native applications

            • No need for separate application server installation

            Interview Summary

            An embedded server in Spring Boot allows the application to run with its own internal web server (Tomcat by default), eliminating the need for external server deployment.


            What is application.properties vs application.yml?

            Both are used for externalized configuration in Spring Boot.

            application.properties

            • Key-value format

            • Simple and flat structure

            • Easy for small configurations

            Example:

            server.port=8081
            spring.datasource.url=jdbc:mysql://localhost:3306/test

            application.yml

            • YAML format (Hierarchical)

            • Uses indentation

            • Cleaner and more readable for complex configuration

            Example:

            server:
            port: 8081
            spring:
            datasource:
            url: jdbc:mysql://localhost:3306/test

            YAML Advantages

            • Hierarchical structure

            • Cleaner and more readable

            • Better for nested configuration

            • Less repetition

            Interview Summary

            Both files serve the same purpose. application.properties uses flat key-value pairs,

            while application.yml provides a cleaner hierarchical structure, preferred for complex configurations.


            What is Spring Boot Actuator?

            Answer:

            • Provides production-ready monitoring and management endpoints

            • Helps monitor application health, metrics, and environment

            • Used mainly in production environments

            Common Actuator Endpoints

            • /actuator/health → Application health status

            • /actuator/metrics → Performance metrics

            • /actuator/info → Custom app information

            • /actuator/env → Environment properties

            • /actuator/beans → List of Spring beans

            Enable Actuator

            Add dependency:

            <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-starter-actuator</artifactId>
            </dependency>

            Expose endpoints:

            management.endpoints.web.exposure.include=*

            Real-Time Usage

            • Kubernetes health checks (/health)

            • Monitoring via Prometheus & Grafana

            • Checking DB connectivity

            • Observing memory, CPU, request metrics

            Interview Summary

            Spring Boot Actuator provides built-in production monitoring endpoints to check health, metrics, environment, and application state.


            What is @ConfigurationProperties?

            Answer:

            • Maps application properties to a Java class

            • Binds multiple related properties using a prefix

            • Cleaner alternative to multiple @Value annotations

            • Used for centralized configuration management

            Example

            application.yml:

            app:
            name: MyApplication
            version: 1.0

            Java class:

            @ConfigurationProperties(prefix = "app")
            @Component
            public class AppConfig {
            private String name;
            private String version;

            // getters and setters
            }

            Spring automatically binds app.name and app.version to the fields.

            Best Practice

            Use with:

            @EnableConfigurationProperties

            (If not using @Component)

            Used In

            • Database configuration

            • External API configs

            • Feature flags

            • Centralized application settings

            Interview Summary

            @ConfigurationProperties binds grouped properties from application files into a strongly typed Java class, making configuration cleaner and maintainable.


            What is CommandLineRunner?

            Answer:

            • Interface in Spring Boot

            • Executes code after the application context is fully started

            • Runs once during startup

            • Used for initialization logic

            Example

            @Component
            class InitRunner implements CommandLineRunner {

            @Override
            public void run(String... args) {
            System.out.println("App Started");
            }
            }

            The run() method executes after Spring Boot starts.

            Passing Arguments

            You can pass arguments while starting the app:

            java -jar app.jar --name=Siraj

            Access inside:

            public void run(String... args) {
            for (String arg : args) {
            System.out.println(arg);
            }
            }

            Real-Time Usage

            • Seed database on startup

            • Load initial configuration

            • Create default admin user

            • Run migration or setup tasks

            Interview Summary

            CommandLineRunner is used to execute code immediately after Spring Boot application startup, commonly for initialization or setup tasks.


            What is DevTools?

            Answer:

            • Improves developer productivity

            • Automatically restarts application when code changes

            • Supports Live Reload in browser

            • Disables caching during development

            Dependency

            <dependency>
            <groupId>org.springframework.boot</groupId>
            <artifactId>spring-boot-devtools</artifactId>
            </dependency>

            Features

            • Automatic restart on classpath changes

            • LiveReload support for frontend changes

            • Faster development feedback cycle

            • Development-only (not included in production build by default)

            Real-Time Usage

            • Modify controller → App restarts automatically

            • Update HTML/Thymeleaf → Browser reloads

            • Faster development without manual restart

            Interview Summary

            Spring Boot DevTools enhances developer productivity by enabling automatic restart and live reload during development.


            What is Spring Boot Logging?

            Answer:

            • Spring Boot uses Logback as the default logging framework

            • Automatically configured via spring-boot-starter-logging

            • No manual setup required

            Common Log Levels

            • TRACE → Detailed internal information

            • DEBUG → Debugging information

            • INFO → General application events

            • WARN → Potential issues

            • ERROR → Serious failures

            Example

            private static final Logger log =
            LoggerFactory.getLogger(UserService.class);

            log.info("User created");
            log.debug("User details: {}", user);
            log.error("Error occurred");

            Configure Log Level

            application.properties:

            logging.level.com.app=DEBUG

            This enables DEBUG logs for package com.app.

            Real-Time Usage

            • Debug production issues

            • Monitor application behavior

            • Track errors and warnings

            Interview Summary

            Spring Boot uses Logback by default and supports multiple log levels that can be configured using logging.level properties.


            What is Spring Boot Packaging?

            Spring Boot applications can be packaged in two main ways:

            JAR (Recommended)

            • Default and recommended packaging

            • Includes embedded server (Tomcat by default)

            • Runs independently

            • Suitable for microservices and cloud deployments

            Example:

            <packaging>jar</packaging>

            Run using:

            java -jar app.jar

            WAR

            • Used to deploy on external application server

            • Requires standalone Tomcat, Jetty, etc.

            • Traditional deployment model

            • Requires extending SpringBootServletInitializer

            Example:

            <packaging>war</packaging>

            Example (WAR Packaging)

            @SpringBootApplication
            public class App extends SpringBootServletInitializer {

            @Override
            protected SpringApplicationBuilder configure(SpringApplicationBuilder builder) {
            return builder.sources(App.class);
            }
            }

            This allows external server to bootstrap the Spring Boot application.

            Real-Time Usage

            • JAR → Microservices, Docker, Kubernetes

            • WAR → Legacy enterprise environments

            Interview Summary

            Spring Boot can be packaged as a JAR (recommended, embedded server) or WAR (for deployment on external servers, requires extending SpringBootServletInitializer).


            What is Externalized Configuration?

            • Allows configuring application without changing code

            • Keeps configuration separate from application logic

            • Supports multiple configuration sources

            Spring Boot supports configuration from:

            • application.properties

            • application.yml

            • Environment variables

            • Command-line arguments

            • System properties

            • Cloud Config Server

            Example

            application.properties:

            server.port=8081

            Environment variable:

            SERVER_PORT=9090

            Command line:

            java -jar app.jar --server.port=7070

            Priority Order (High → Low)

            1. Command-line arguments

            2. Environment variables

            3. application.properties / application.yml

            4. Default values in code

            Higher priority overrides lower priority.

            Real-Time Usage

            • Different DB config for dev and prod

            • Set secrets using environment variables

            • Override port in cloud deployment

            Interview Summary

            Externalized configuration allows Spring Boot applications to read configuration from multiple sources with a defined priority order, enabling flexible and environment-specific setups.


            What is Banner in Spring Boot?

            • ASCII art displayed when application starts

            • Shown in console during startup

            • Used for branding or customization

            Default Banner

            Spring Boot displays a default ASCII banner when the app starts.

            Custom Banner

            Create file:

            src/main/resources/banner.txt

            Example Stylish banner.txt

            ____ _ _
            / ___|| |_ __ _ _ __| |_ ___
            \___ \| __/ _` | '__| __/ _ \
            ___) | || (_| | | | || __/
            |____/ \__\__,_|_| \__\___|

            :: My Application ::
            :: Version 1.0.0 ::
            :: Powered by ABC Company ::

            This can be used to:

            • Display application name

            • Show version information

            • Add company branding

            Spring Boot automatically loads and prints it during startup.

            Disable Banner

            application.properties:

            spring.main.banner-mode=off

            Interview Summary

            Spring Boot Banner is the ASCII startup text displayed in console and can be customized using banner.txt for branding and application information.


              What is Lazy Initialization in Spring Boot?

              Allows beans to be initialized only when they are first requested instead of at application startup.

              Enable:

              • spring.main.lazy-initialization=true

              • Improves startup time
              • Reduces initial memory usage
              • Beans created only when needed
              • Useful for large applications

              Priority: Applies to all beans unless explicitly disabled.


              What is Spring Boot CLI?

              • Command-line tool provided by Spring Boot

              • Allows running Spring applications using Groovy scripts

              • Eliminates need for full project setup

              • Automatically handles dependencies

              Example

              Create a Groovy file:

              @RestController
              class HelloController {
              @GetMapping("/")
              String hello() {
              "Hello World"
              }
              }

              Run using:

              spring run app.groovy

              Spring Boot CLI automatically downloads required dependencies and starts embedded server.

              Features

              • Quick prototyping

              • Minimal configuration

              • Auto dependency resolution

              Real-Time Usage

              • Rapid development

              • Learning and demos

              • Prototyping

              Rarely used in production systems.

              Interview Summary

              Spring Boot CLI is a command-line tool that allows running Spring applications quickly using Groovy scripts, mainly used for prototyping and learning.


              What is Spring Boot Test?

              Spring Boot Test is a testing framework that provides built-in support for testing Spring Boot applications.

              • Supports unit, integration, and slice testing
              • Can load full or partial application context
              • Provides specialized testing annotations
              • Integrates with JUnit and Mockito

              Common Annotations

              • @SpringBootTest
              Loads the entire application context (Full Integration Testing).

              • @WebMvcTest
              Loads only the Web layer (Controllers, Filters, MVC components).

              • @DataJpaTest
              Loads only JPA components (Repositories, EntityManager, Embedded DB).

              • @MockBean
              Creates and injects mock beans into the Spring context.

              Example – Full Integration Test

              @SpringBootTest
              class UserServiceTest {

              @Autowired
              private UserService userService;

              @Test
              void testService() {
              assertNotNull(userService);
              }
              }

              Example – Web Layer Test

              @WebMvcTest(UserController.class)
              class UserControllerTest {

              @Autowired
              private MockMvc mockMvc;

              @MockBean
              private UserService userService;
              }

              Types of Testing You Can Perform

              • Unit Testing → Without Spring context
              • Integration Testing → Using @SpringBootTest
              • Web Layer Testing → Using @WebMvcTest
              • Repository Testing → Using @DataJpaTest
              • Mock-Based Testing → Using @MockBean

              Real-Time Usage

              • End-to-end integration testing
              • Layer-specific (slice) testing
              • Testing REST APIs with MockMvc
              • Mocking dependencies in controllers/services

              Interview Summary

              Spring Boot Test enables unit, integration, and slice testing using specialized annotations such as @SpringBootTest, @WebMvcTest, and @DataJpaTest. It simplifies testing by auto-configuring the Spring context and integrating seamlessly with modern testing tools.


              What is Custom Starter in Spring Boot?

              • A reusable dependency that provides auto-configuration

              • Used to standardize common setup across projects

              • Contains:

                • Auto-config class

                • Properties class

                • Conditional beans

              Example

              Auto-Configuration

              @Configuration
              @ConditionalOnClass(MyService.class)
              public class MyStarterAutoConfig {

              @Bean
              @ConditionalOnMissingBean
              public MyService myService() {
              return new MyService();
              }
              }

              Properties

              @ConfigurationProperties(prefix = "my.starter")
              public class MyStarterProperties {
              private String message;
              }

              Usage

              my.starter.message=Hello

              Used in:

              • Company-wide logging

              • Common security module


              What is Graceful Shutdown?

              Graceful Shutdown allows a Spring Boot application to stop safely without interrupting active requests.

              • Finishes ongoing requests
              • Stops accepting new requests
              • Closes connections safely
              • Prevents partial transactions

              Enable

              Add in application.properties:

              server.shutdown=graceful

              (Optional timeout)

              spring.lifecycle.timeout-per-shutdown-phase=30s

              Used In

              • Kubernetes deployments
              • Production releases
              • Rolling updates

              Interview Summary

              Graceful Shutdown ensures active requests complete before the application stops, preventing data loss during production deployments.


              What is HikariCP?

              HikariCP is the default database connection pool used in Spring Boot.

              • High-performance and lightweight
              • Faster than traditional connection pools
              • Auto-configured when using JDBC
              • Efficient resource management

              Configuration Example

              spring.datasource.hikari.maximum-pool-size=20

              Common properties:

              • maximum-pool-size
              • minimum-idle
              • connection-timeout

              Used In

              • High-traffic applications
              • Production environments
              • Microservices with database access

              Interview Summary

              HikariCP is the default, high-performance JDBC connection pool in Spring Boot, designed for speed, low latency, and efficient database connection management.


              How Connection Pooling Works?

              Connection Pooling manages a set of reusable database connections.

              • Maintains a pool of open DB connections
              • Request → Borrows connection from pool
              • After use → Returns connection to pool
              • Avoids repeated open/close operations

              Why It Is Needed

              Opening a database connection is expensive.
              Connection pooling reuses existing connections to improve performance.

              Benefits

              • Faster response time
              • Better scalability
              • Efficient resource utilization
              • Prevents database overload

              Interview Summary

              Connection Pooling improves performance by reusing database connections instead of creating a new one for every request, ensuring faster and more scalable applications.







              4️⃣ Spring Data JPA


              What is Spring Data JPA?

              Spring Data JPA is an abstraction layer over JPA (Java Persistence API) that simplifies database access.

              • Reduces boilerplate DAO code
              • Built on top of ORM frameworks like Hibernate
              • Provides repository-based data access
              • Automatically implements common operations

              Key Features

              • Automatic CRUD methods
              • Query method generation (findByName, findByEmail, etc.)
              • Pagination and sorting support
              • Custom JPQL and Native queries
              • Auditing support (createdDate, modifiedDate)

              Real-Time Example

              Instead of writing large DAO implementations:

              public interface UserRepository extends JpaRepository<User, Long> {
              }

              No need to write:

              • EntityManager code
              • Transaction handling
              • Manual CRUD queries

              Interview Summary

              Spring Data JPA simplifies database interaction by providing ready-made repository interfaces, automatic query generation, and reduced boilerplate code on top of JPA and Hibernate.


              What is ORM (Object Relational Mapping)?

              ORM is a technique that maps Java objects to database tables.

              • Converts Java classes into database tables
              • Maps object fields to table columns
              • Eliminates manual JDBC coding
              • Generates SQL automatically
              • Handles CRUD operations internally

              Popular ORM Frameworks (Java)

              • Hibernate (most widely used)
              • EclipseLink
              • Spring Data JPA (built on top of JPA providers like Hibernate)
              • MyBatis (SQL mapper alternative, widely used in enterprise apps)

              Example

              @Entity
              class User {

              @Id
              @GeneratedValue
              private Long id;

              private String name;
              }

              Maps to table:

              USER

              | id | name |

              Real-Time Usage

              • Converts database rows into Java objects automatically
              • Persists Java objects into database tables
              • Used in enterprise applications and microservices
              • Reduces boilerplate SQL and JDBC code

              Interview Summary

              ORM (Object Relational Mapping) maps Java objects to database tables, automatically handling SQL generation and object conversion. Hibernate is the most popular ORM currently used in the Java ecosystem.


              What is Hibernate?

              Hibernate is the most popular JPA implementation used for ORM in Java applications.

              • Implements JPA specification
              • Converts HQL/JPQL into SQL
              • Manages caching and performance
              • Supports lazy loading
              • Performs dirty checking automatically

              Key Responsibilities

              • SQL generation
              • Connection handling
              • Transaction synchronization
              • Object state management (Transient, Persistent, Detached)
              • First-level and second-level caching

              How It Works

              • Maps Java entities to database tables
              • Converts object operations into SQL queries
              • Synchronizes object state with database automatically

              Real-Time Usage

              • Enterprise applications
              • Spring Boot applications with JPA
              • High-performance database-driven systems

              Interview Summary

              Hibernate is a widely used JPA implementation that handles ORM by generating SQL, managing transactions, caching, lazy loading, and synchronizing Java object states with the database.


                What is JPA?

                JPA (Java Persistence API) is a specification for ORM in Java.

                • Not an implementation
                • Defines standard APIs for ORM
                • Specifies how objects map to database tables
                • Provides annotations like @Entity, @Id, @OneToMany

                Important Concept

                JPA → Rules (Specification)
                Hibernate → Implementation (Provider)

                Other implementations:

                • EclipseLink
                • OpenJPA

                What JPA Defines

                • Entity mapping rules
                • JPQL (Java Persistence Query Language)
                • Entity lifecycle management
                • Caching and transaction guidelines

                Real-Time Usage

                • Used in Spring Boot via Spring Data JPA
                • Works with providers like Hibernate
                • Standard way to perform ORM in Java

                Interview Summary

                JPA is a specification that defines ORM standards in Java, while frameworks like Hibernate implement those rules to provide actual database functionality.


                What is Entity Lifecycle in JPA?

                Entity Lifecycle refers to the different states an entity goes through while interacting with the persistence context.

                Entity States

                • Transient → Object created using new, not managed by EntityManager, not stored in DB

                • Persistent → Managed by EntityManager, synchronized with database

                • Detached → Previously managed, but no longer attached to persistence context

                • Removed → Marked for deletion, will be deleted from DB on commit

                How It Works

                • Transient → persist() → Persistent
                • Persistent → detach() / session closed → Detached
                • Persistent → remove() → Removed

                Real-Time Example

                Fetch entity → modify fields → commit transaction

                Hibernate automatically updates database using dirty checking (no explicit update query needed).

                Interview Summary

                Entity Lifecycle in JPA defines how an entity transitions between Transient, Persistent, Detached, and Removed states while being managed by the EntityManager.


                What is JpaRepository?

                JpaRepository is a Spring Data interface that provides ready-made database operations for JPA entities.

                • Extends CrudRepository
                • Extends PagingAndSortingRepository
                • Provides additional JPA-specific features

                Provides Methods

                • save()
                • findById()
                • findAll()
                • delete()
                • existsById()
                • Pagination and sorting support

                Example

                public interface UserRepo extends JpaRepository<User, Long> {
                }

                No need to write:

                • DAO implementation
                • EntityManager code
                • Manual CRUD queries

                Real-Time Usage

                • Used in Spring Boot applications
                • Automatically generates queries
                • Supports custom query methods

                Interview Summary

                JpaRepository is a powerful Spring Data interface that extends CrudRepository and PagingAndSortingRepository, providing built-in CRUD operations and pagination without requiring manual DAO implementation.


                Difference Between save() and saveAndFlush()

                Both methods are provided by JpaRepository but behave differently regarding database synchronization.

                save()

                • Saves entity to persistence context
                • Does NOT immediately write to database
                • DB synchronization happens at transaction commit
                • Faster when multiple operations are involved

                saveAndFlush()

                • Saves entity
                • Immediately flushes changes to database
                • Forces synchronization with DB
                • Useful when immediate DB consistency is required

                What is Flush?

                Flush means:

                • Synchronizing persistence context with database
                • Executes SQL statements immediately
                • Does not commit transaction

                Used When

                • Need immediate database visibility
                • Stored procedures depend on inserted data
                • Validation requires DB-level constraints instantly

                Interview Summary

                save() delays database synchronization until transaction commit, while saveAndFlush() forces immediate synchronization with the database using flush(), ensuring instant consistency.


                What is Dirty Checking?

                Dirty Checking is a Hibernate mechanism that automatically detects changes made to a managed entity and updates the database without explicitly calling update().

                • Hibernate tracks changes to managed entities
                • No need to call update() manually
                • Works inside a transaction
                • Executes SQL at commit time

                How It Works

                When an entity is in Persistent (managed) state:

                • Hibernate keeps a snapshot of original values
                • When transaction commits, it compares current values with the snapshot
                • If changes are detected → UPDATE query is executed automatically

                Example

                @Transactional
                public void updateUser() {

                User user = repo.findById(1L).get(); // Entity becomes Persistent

                user.setName("New Name"); // Modify entity

                } // Transaction commit → Hibernate automatically updates DB

                No explicit save() or update() call is required.

                Important Conditions

                • Must be inside a transaction
                • Entity must be managed by EntityManager
                • Does not work for Detached entities

                Interview Summary

                Dirty Checking is Hibernate’s automatic change detection mechanism that updates the database when a managed entity is modified, without requiring an explicit update() call.


                What is FetchType.LAZY vs FetchType.EAGER?

                FetchType defines how related entities are loaded from the database.

                FetchType.LAZY

                • Loads related data only when accessed
                • Default for @OneToMany and @ManyToMany
                • Improves performance
                • Avoids unnecessary data loading

                Example:

                @OneToMany(fetch = FetchType.LAZY)
                private List<OrderItem> items;

                Data is loaded only when:

                order.getItems();

                FetchType.EAGER

                • Loads related data immediately with parent entity
                • Default for @ManyToOne and @OneToOne
                • Can impact performance if large data

                Example:

                @ManyToOne(fetch = FetchType.EAGER)
                private Customer customer;

                Real-Time Example

                When loading an Order:

                • LAZY → Order loads first, OrderItems load only when accessed
                • EAGER → Order and all OrderItems load together

                Interview Summary

                FetchType.LAZY loads related entities only when needed, improving performance, while FetchType.EAGER loads related entities immediately with the parent entity.


                What is N+1 Problem?

                The N+1 Problem occurs when fetching parent entities triggers additional queries for each related child entity.

                How It Happens

                • 1 query loads parent records
                • N additional queries load child data

                Example:

                • 1 query → Load 100 Orders
                • 100 queries → Load OrderItems for each Order

                Total = 101 queries

                Why It Is a Problem

                • Performance degradation
                • Increased database load
                • Slower response time

                Solutions

                • Use JOIN FETCH
                • Use EntityGraph
                • Use batch fetching

                Example – Using JOIN FETCH

                @Query("SELECT o FROM Order o JOIN FETCH o.items")
                List<Order> findAllOrdersWithItems();

                Loads Orders and OrderItems in a single query.

                Example – Using EntityGraph

                @EntityGraph(attributePaths = {"items"})
                @Query("SELECT o FROM Order o")
                List<Order> findAllOrders();

                EntityGraph tells Hibernate to fetch the "items" association eagerly in one query.

                Example – Using Batch Fetching

                Enable batch size:

                spring.jpa.properties.hibernate.default_batch_fetch_size=10

                Or on entity:

                @BatchSize(size = 10)
                @OneToMany(fetch = FetchType.LAZY)
                private List<OrderItem> items;

                Batch fetching loads child entities in groups instead of one-by-one.

                Interview Summary

                The N+1 Problem occurs when one query loads parent entities and additional queries load each child entity separately. It can be solved using JOIN FETCH, EntityGraph, or batch fetching to reduce the number of SQL queries.


                What is @Transactional?

                @Transactional is an annotation used to manage database transactions declaratively in Spring.

                • Automatically starts a transaction
                • Commits if method completes successfully
                • Rolls back if an exception occurs
                • Can be applied at method or class level

                Example

                @Transactional
                public void processOrder() {

                orderRepository.save(order);
                paymentService.processPayment(order);

                }

                If everything succeeds → Transaction commits
                If RuntimeException occurs → Transaction rolls back

                Default Behavior

                • Rollback on RuntimeException
                • Does NOT rollback on Checked Exception (by default)
                • Commit on successful execution

                Real-Time Usage

                • Service layer methods
                • Business operations involving multiple DB calls
                • Ensuring data consistency

                Interview Summary

                @Transactional is used to manage transactions declaratively in Spring. It ensures commit on success and rollback on runtime exceptions, maintaining data consistency.


                What are Transaction Propagation Types?

                Transaction propagation defines how a transaction behaves when one transactional method calls another transactional method.

                Main Propagation Types

                • REQUIRED (Default)
                Joins existing transaction if present, otherwise creates a new one.

                • REQUIRES_NEW
                Always creates a new transaction. Suspends existing transaction.

                • SUPPORTS
                Joins existing transaction if present, otherwise runs without transaction.

                • MANDATORY
                Must run inside an existing transaction. Throws exception if none exists.

                • NEVER
                Must run without a transaction. Throws exception if transaction exists.

                • NOT_SUPPORTED
                Runs without a transaction. Suspends existing transaction if present.

                Examples

                1. REQUIRED (Default)

                • Joins existing transaction
                • Creates new one if none exists

                @Transactional
                public void placeOrder() {
                paymentService.processPayment(); // joins SAME transaction
                }

                @Transactional(propagation = Propagation.REQUIRED)
                public void processPayment() {
                // Runs in SAME transaction as placeOrder()
                }

                If payment fails → Entire transaction rolls back.

                2. REQUIRES_NEW

                • Always creates new transaction
                • Suspends existing transaction

                @Transactional
                public void placeOrder() {
                paymentService.processPayment(); // runs in NEW transaction
                }

                @Transactional(propagation = Propagation.REQUIRES_NEW)
                public void processPayment() {
                // Runs in NEW independent transaction
                }

                If payment fails → Only payment rolls back
                Main transaction can continue.

                3. SUPPORTS

                @Transactional(propagation = Propagation.SUPPORTS)
                public void viewOrder() {
                // Runs WITH transaction if exists
                // Runs WITHOUT transaction if none exists
                }

                4. MANDATORY

                @Transactional(propagation = Propagation.MANDATORY)
                public void updateOrder() {
                // Requires active transaction
                }

                If called without transaction → IllegalTransactionStateException

                5. NEVER

                @Transactional(propagation = Propagation.NEVER)
                public void logInfo() {
                // Must NOT execute inside transaction
                }

                6. NOT_SUPPORTED

                @Transactional(propagation = Propagation.NOT_SUPPORTED)
                public void generateReport() {
                // Executes outside transaction
                }

                Real-Time Usage

                • PaymentService → REQUIRES_NEW (independent transaction)
                • Audit logging → REQUIRES_NEW (ensure logs are saved even if main fails)
                • Main business flow → REQUIRED
                • Read-only operations → SUPPORTS
                • Reporting → NOT_SUPPORTED

                Interview Summary

                Transaction propagation controls how transactions interact when one method calls another. REQUIRED joins or creates a transaction, while REQUIRES_NEW always creates a separate independent transaction.


                What are Isolation Levels?

                Isolation levels define how transactions are isolated from each other and control visibility of data changes.

                Isolation Levels

                • READ_UNCOMMITTED
                Can read uncommitted data (Dirty Read possible).

                • READ_COMMITTED
                Can read only committed data (Prevents Dirty Read).

                • REPEATABLE_READ
                Prevents Dirty Read and Non-repeatable Read.

                • SERIALIZABLE
                Highest isolation level. Prevents Dirty Read, Non-repeatable Read, and Phantom Read.

                Common Issues

                • Dirty Read
                Reading data that is not yet committed.

                • Non-repeatable Read
                Same query returns different results within same transaction.

                • Phantom Read
                New rows appear when the same query is executed again.

                Examples with Comments

                READ_UNCOMMITTED

                @Transactional(isolation = Isolation.READ_UNCOMMITTED)
                public void checkBalance() {
                // May read data not yet committed by another transaction
                }

                Scenario:
                Transaction A updates balance but does not commit.
                Transaction B reads that uncommitted value → Dirty Read.

                READ_COMMITTED

                @Transactional(isolation = Isolation.READ_COMMITTED)
                public void viewAccount() {
                // Reads only committed data
                }

                Scenario:
                Transaction A reads balance = 5000
                Transaction B updates to 7000 and commits
                Transaction A reads again → sees 7000 (Non-repeatable Read possible)

                REPEATABLE_READ

                @Transactional(isolation = Isolation.REPEATABLE_READ)
                public void processLoan() {
                // Same row values remain consistent during transaction
                }

                Scenario:
                Transaction A reads balance = 5000
                Transaction B updates and commits
                Transaction A reads again → still sees 5000

                SERIALIZABLE

                @Transactional(isolation = Isolation.SERIALIZABLE)
                public void criticalTransfer() {
                // Transactions behave as if executed one after another
                }

                Scenario:
                Transaction A selects records
                Transaction B tries to insert matching records
                Transaction B waits until A completes (Prevents Phantom Read)

                Real-Time Usage

                • Banking systems → REPEATABLE_READ or SERIALIZABLE
                • Financial transactions → Higher isolation levels
                • Reporting systems → READ_COMMITTED

                Interview Summary

                Isolation levels control how transactions view changes made by other transactions. Higher isolation ensures stronger consistency but may reduce performance and concurrency.


                What is First-Level Cache?

                First-Level Cache is the default cache mechanism in JPA and Hibernate.

                • Enabled automatically
                • Session-level cache (EntityManager level)
                • Stores entities within the current transaction/session
                • Improves performance by avoiding repeated DB queries

                Is It JPA or Hibernate Specific?

                • Defined by JPA specification
                • Mandatory for all JPA implementations
                • Implemented by ORM providers like Hibernate, EclipseLink, OpenJPA
                • Not Hibernate-only

                In JPA, First-Level Cache is called the Persistence Context.

                How It Works

                • When an entity is fetched → Stored in persistence context
                • If fetched again within same session → Returned from cache
                • No additional SQL query executed
                • Exists only for the duration of the transaction/session

                Example

                @Transactional
                public void getUser() {

                User user1 = entityManager.find(User.class, 1L); // Hits DB

                User user2 = entityManager.find(User.class, 1L); // Returned from cache

                }

                Explanation:

                • First call → Executes SELECT query
                • Second call → Uses First-Level Cache
                • No second database hit

                Important Characteristics

                • Session-level (per EntityManager)
                • Automatically enabled
                • Cannot be disabled
                • Cleared when session ends

                Interview Summary

                First-Level Cache is the default session-level cache defined by JPA and implemented by ORM providers like Hibernate. It stores entities within the persistence context and prevents repeated database queries within the same transaction.


                What is Second-Level Cache?

                Second-Level Cache is a shared cache across multiple sessions (EntityManager instances).

                • Shared across sessions
                • Improves application performance
                • Reduces repeated database queries
                • Stores entities beyond a single transaction
                • Requires explicit configuration

                Difference from First-Level Cache

                • First-Level Cache → Session-level (default, always enabled)
                • Second-Level Cache → Application-level (shared, configurable)

                How It Works

                • Entity is fetched from DB → Stored in cache
                • Next time any session requests same entity → Returned from cache
                • Reduces database load

                Tools / Providers

                • EhCache
                • Hazelcast
                • Infinispan

                Hibernate integrates with these caching providers.

                Example (Enable in properties)

                spring.jpa.properties.hibernate.cache.use_second_level_cache=true
                spring.jpa.properties.hibernate.cache.region.factory_class=org.hibernate.cache.jcache.JCacheRegionFactory

                Real-Time Usage

                • High-traffic applications
                • Frequently read data (e.g., product catalog)
                • Microservices with heavy read operations

                Interview Summary

                Second-Level Cache is a shared, configurable cache used by Hibernate to store entities across sessions, reducing database access and improving performance.


                  What is JPQL?

                  JPQL (Java Persistence Query Language) is a query language defined by JPA to query entities.

                  • Works on entity names, not table names
                  • Uses entity fields, not column names
                  • Database-independent
                  • Translated into SQL by JPA provider (e.g., Hibernate)

                  Key Difference

                  SQL → Works on tables and columns
                  JPQL → Works on entities and object fields

                  Example

                  @Query("SELECT u FROM User u WHERE u.name = :name")
                  List<User> findByName(@Param("name") String name);

                  Explanation:

                  • User → Entity name (not table name)
                  • u.name → Entity field (not column name)
                  • :name → Named parameter

                  Hibernate converts this JPQL into SQL internally.

                  Real-Time Usage

                  • Custom queries in Spring Data JPA
                  • Complex filtering and joins
                  • Pagination and sorting

                  Interview Summary

                  JPQL is a database-independent query language in JPA that operates on entities and their fields, and is converted into SQL by the JPA provider.


                  What is Native Query?

                  A Native Query is a direct SQL query executed against the database.

                  • Uses actual table names and column names
                  • Database-specific
                  • Bypasses JPQL abstraction
                  • Executed directly by the database

                  Example

                  @Query(value = "SELECT * FROM users", nativeQuery = true)
                  List<User> findAllUsers();

                  Explanation:

                  • users → Table name
                  • Uses raw SQL syntax
                  • nativeQuery = true → Tells Spring Data JPA it is SQL, not JPQL

                  Used When

                  • Complex SQL queries
                  • Database-specific features (e.g., MySQL functions, PostgreSQL JSON)
                  • Performance-optimized queries
                  • Stored procedures

                  JPQL vs Native Query

                  • JPQL → Works on entities (database-independent)
                  • Native Query → Works on tables (database-specific)

                  Interview Summary

                  A Native Query is a raw SQL query executed directly against the database, used when JPQL is insufficient or when database-specific features are required.


                  What is Pagination and Sorting?

                  Pagination and Sorting are features in Spring Data JPA used to retrieve data in smaller chunks and in a specific order.

                  • Pagination → Retrieves limited records per page
                  • Sorting → Orders records (ASC/DESC)
                  • Improves performance for large datasets
                  • Prevents loading entire table into memory

                  Pagination Example

                  Page<User> users = repo.findAll(PageRequest.of(0, 10));

                  Explanation:

                  • 0 → Page number (first page)
                  • 10 → Number of records per page

                  Pagination with Sorting Example

                  Page<User> users = repo.findAll(
                  PageRequest.of(0, 10, Sort.by("name").ascending())
                  );

                  Sorts users by name in ascending order.

                  Used In

                  • Large datasets
                  • REST APIs
                  • Admin dashboards
                  • Search results

                  Interview Summary

                  Pagination and Sorting in Spring Data JPA allow efficient data retrieval by limiting results per page and ordering them, improving performance and scalability in large applications.


                  What is Auditing in JPA?

                  Auditing in JPA is used to automatically track entity creation and modification details.

                  • Tracks CreatedDate
                  • Tracks ModifiedDate
                  • Tracks CreatedBy
                  • Tracks LastModifiedBy
                  • Managed automatically by Spring Data JPA

                  Step 1: Enable Auditing

                  @EnableJpaAuditing
                  @SpringBootApplication
                  public class Application {
                  }

                  Step 2: Add Entity Listener

                  @Entity
                  @EntityListeners(AuditingEntityListener.class)
                  public class User {

                  Step 3: Add Audit Fields

                  @CreatedDate
                  private LocalDateTime createdAt;

                  @LastModifiedDate
                  private LocalDateTime updatedAt;

                  @CreatedBy
                  private String createdBy;

                  @LastModifiedBy
                  private String modifiedBy;

                  Complete Example

                  @Entity
                  @EntityListeners(AuditingEntityListener.class)
                  public class User {

                  @Id
                  @GeneratedValue
                  private Long id;

                  private String name;

                  @CreatedDate
                  private LocalDateTime createdAt;

                  @LastModifiedDate
                  private LocalDateTime updatedAt;
                  }

                  When:

                  • New User is saved → createdAt is set automatically
                  • Existing User is updated → updatedAt is updated automatically

                  Real-Time Usage

                  • Enterprise applications
                  • Compliance tracking
                  • User activity monitoring
                  • Record history maintenance

                  Interview Summary

                  Auditing in JPA automatically populates creation and modification details using annotations like @CreatedDate and @LastModifiedDate, helping track entity lifecycle changes without manual coding.


                  What is Cascade Type?

                  Cascade Type defines how operations performed on a parent entity are propagated to its related child entities.

                  Cascade Types

                  • PERSIST → Saves child entity when parent is saved

                  • MERGE → Updates child entity when parent is updated

                  • REMOVE → Deletes child entity when parent is deleted

                  • DETACH → Detaches child entity when parent is detached

                  • REFRESH → Refreshes child entity when parent is refreshed

                  • ALL → Applies all cascade types

                  Example

                  @OneToMany(cascade = CascadeType.ALL)
                  private List<OrderItem> items;

                  Meaning:

                  • If Order is saved → OrderItems are saved
                  • If Order is deleted → OrderItems are deleted
                  • If Order is updated → OrderItems are updated

                  Example Scenario

                  Order order = new Order();
                  order.addItem(new OrderItem());

                  orderRepository.save(order);

                  Because of CascadeType.PERSIST or ALL:

                  • Saving Order automatically saves OrderItem
                  • No need to call save() separately

                  Additional Examples

                  PERSIST Example

                  @OneToOne(cascade = CascadeType.PERSIST)
                  private Profile profile;

                  If User is saved → Profile is also saved
                  If User is deleted → Profile is NOT deleted

                  REMOVE Example

                  @OneToMany(cascade = CascadeType.REMOVE)
                  private List<Comment> comments;

                  If Blog is deleted → All Comments are deleted
                  If Blog is saved → Comments are NOT automatically saved

                  MERGE Example

                  @OneToMany(cascade = CascadeType.MERGE)
                  private List<Address> addresses;

                  If User is updated → Address entities are also updated

                  DETACH Example

                  @OneToMany(cascade = CascadeType.DETACH)
                  private List<OrderItem> items;

                  If Order is detached from persistence context →
                  OrderItems are also detached

                  REFRESH Example

                  @OneToMany(cascade = CascadeType.REFRESH)
                  private List<Product> products;

                  If parent entity is refreshed →
                  Child entities are also refreshed from database

                  Real-Time Usage

                  • Parent-Child relationships
                  • Order → OrderItems
                  • User → Addresses
                  • Blog → Comments

                  Interview Summary

                  Cascade Type controls how entity operations like save, update, and delete propagate from parent to child entities, simplifying relationship management in JPA.


                  What is Orphan Removal?

                  Orphan Removal automatically deletes a child entity when it is removed from the parent’s collection.

                  • Deletes child when removed from parent
                  • Works in parent-child relationships
                  • Commonly used with @OneToMany
                  • Prevents orphan records in database

                  Example

                  @OneToMany(mappedBy = "order", orphanRemoval = true)
                  private List<OrderItem> items;

                  Example Scenario

                  order.getItems().remove(item);
                  orderRepository.save(order);

                  Because orphanRemoval = true:

                  • Removed OrderItem is automatically deleted from database
                  • No need to call delete() explicitly

                  Difference Between Cascade REMOVE and Orphan Removal

                  • CascadeType.REMOVE → Deletes children when parent is deleted
                  • orphanRemoval = true → Deletes child when removed from collection

                  Real-Time Usage

                  • Order → OrderItems
                  • User → Addresses
                  • Blog → Comments
                  • Shopping cart → CartItems

                  Interview Summary

                  Orphan Removal ensures that when a child entity is removed from its parent’s collection, it is automatically deleted from the database, preventing orphan records.


                  What is Optimistic vs Pessimistic Locking?

                  Locking is used to handle concurrent data access and prevent data inconsistency.

                  Optimistic Locking

                  • Uses versioning mechanism
                  • Implemented using @Version
                  • Does NOT lock database row immediately
                  • Prevents lost updates
                  • Suitable for low-conflict systems

                  Example

                  @Entity
                  public class Product {

                  @Id
                  private Long id;

                  private String name;

                  @Version
                  private Long version;
                  }

                  How it works:

                  • Two users fetch same record
                  • Both try to update
                  • First update succeeds
                  • Second update fails with OptimisticLockException

                  Pessimistic Locking

                  • Locks database row immediately
                  • Prevents other transactions from modifying it
                  • Suitable for high-conflict systems
                  • Ensures strict consistency

                  Example

                  @Lock(LockModeType.PESSIMISTIC_WRITE)
                  @Query("SELECT p FROM Product p WHERE p.id = :id")
                  Product findByIdForUpdate(@Param("id") Long id);

                  How it works:

                  • First transaction locks the row
                  • Other transactions must wait
                  • Prevents concurrent modification

                  Key Difference

                  • Optimistic → No DB lock, uses version check
                  • Pessimistic → Locks DB row

                  Used In

                  • Banking systems
                  • Inventory systems
                  • Financial transactions
                  • High-concurrency applications

                  Interview Summary

                  Optimistic locking uses a version field to detect conflicts without locking the database row, while pessimistic locking locks the row immediately to prevent concurrent modifications.


                  What is DTO Projection?

                  DTO Projection is a technique where only selected fields are fetched from the database instead of loading the full entity.

                  • Fetches only required columns
                  • Reduces memory usage
                  • Improves performance
                  • Enhances security (avoids exposing sensitive fields)

                  Example – Using JPQL Constructor Expression

                  @Query("SELECT new com.app.UserDTO(u.id, u.name) FROM User u")
                  List<UserDTO> findAllUsers();

                  Explanation:

                  • UserDTO must have a matching constructor
                  • Only id and name are fetched
                  • Other fields (password, email, etc.) are not loaded

                  DTO Class Example

                  public class UserDTO {

                  private Long id;
                  private String name;

                  public UserDTO(Long id, String name) {
                  this.id = id;
                  this.name = name;
                  }
                  }

                  Interface-Based Projection (Alternative)

                  public interface UserView {
                  Long getId();
                  String getName();
                  }
                  List<UserView> findBy();

                  Spring automatically maps selected fields.

                  Improves

                  • Performance (less data fetched)
                  • Security (sensitive fields not exposed)
                  • API response optimization

                  Real-Time Usage

                  • REST APIs
                  • Large tables with many columns
                  • Public API responses
                  • Microservices communication

                  Interview Summary

                  DTO Projection allows fetching only required fields instead of full entities, improving performance and security by reducing unnecessary data loading.


                  What is LazyInitializationException?

                  LazyInitializationException occurs when a lazily loaded entity field is accessed outside an active transaction or persistence context.

                  When It Occurs

                  • Entity has FetchType.LAZY
                  • Transaction/session is already closed
                  • Lazy field is accessed afterward

                  Example Scenario

                  @Transactional
                  public Order getOrder() {
                  return orderRepository.findById(1L).get();
                  }

                  Later:

                  order.getItems(); // LazyInitializationException

                  Reason:

                  • items is LAZY
                  • Transaction already closed
                  • Hibernate cannot load data

                  Solutions

                  • Use JOIN FETCH
                  • Use DTO Projection
                  • Use OpenSessionInView (not recommended for production)

                  Example – JOIN FETCH

                  @Query("SELECT o FROM Order o JOIN FETCH o.items WHERE o.id = :id")
                  Order findOrderWithItems(@Param("id") Long id);

                  Loads items within the transaction.

                  Example – DTO Projection

                  Fetch required data directly:

                  @Query("SELECT new com.app.OrderDTO(o.id, o.name) FROM Order o")

                  Avoids lazy loading problem.

                  Interview Summary

                  LazyInitializationException occurs when a lazily loaded association is accessed after the session is closed. It can be avoided using JOIN FETCH, DTO projection, or proper transaction management.