SPB Guide
SPB Guide
Guide
Spring Boot Development Expert
2025-10-03
Contents
1 Introduction 3
1
8.2.3 Repository Layer . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
8.2.4 Entity (Model) . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
10 Learning Roadmap 13
10.1 Phase 1: Java Fundamentals . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
10.2 Phase 2: Spring Boot Basics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
10.3 Phase 3: Building REST APIs . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
10.4 Phase 4: Database Integration . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
10.5 Phase 5: Advanced Topics . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 14
12 Configuration Files 19
12.1 application.properties . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 19
13 Summary 19
14 Next Steps 20
2
1 Introduction
Welcome to Spring Boot! If you’re coming from the MERN Stack (MongoDB, Express, React,
Node.js), you already have a solid foundation in backend development. Spring Boot will feel
familiar in many ways, but with some key differences.
This guide will help you understand the core concepts of Spring Boot by drawing parallels
to what you already know from MERN development.
3
3.2 The MVC Flow
Application Flow
CLIENT (Browser/App)
↓ HTTP Request
CONTROLLER LAYER
(Handles requests, calls services)
@RestController / @Controller
↓
SERVICE LAYER
(Business logic, validation)
@Service
↓
REPOSITORY LAYER
(Database operations)
@Repository / JPA Repository
↓
DATABASE (MySQL, PostgreSQL)
1 // Express route
2 app . get ( ’/ api / users /: id ’ , async ( req , res ) = > {
3 try {
4 const user = await User . findById ( req . params . id ) ;
5 res . json ( user ) ;
6 } catch ( error ) {
7 res . status (500) . json ({ error : error . message }) ;
8 }
9 }) ;
1 @RestController
2 @RequestMapping ( " / api / users " )
3 public class UserController {
4
4
5 @Autowired
6 private UserService userService ;
7
8 @GetMapping ( " /{ id } " )
9 public ResponseEntity < User > getUser ( @PathVariable Long id ) {
10 User user = userService . getUserById ( id ) ;
11 return ResponseEntity . ok ( user ) ;
12 }
13 }
Annotation Description
@RestController Marks class as REST API controller (returns JSON data)
@Controller Marks class as web controller (returns HTML views)
@RequestMapping Defines base URL path for all methods in controller
@GetMapping Maps HTTP GET requests to handler method
@PostMapping Maps HTTP POST requests to handler method
@PutMapping Maps HTTP PUT requests to handler method
@DeleteMapping Maps HTTP DELETE requests to handler method
@PathVariable Extracts values from URL path (like req.params in Ex-
press)
@RequestParam Extracts query parameters (like req.query in Express)
@RequestBody Extracts request body (like req.body in Express)
Table 2: Spring Boot Controller Annotations
5
5.2 Why Separate Service Layer?
Benefits of Service Layer
1 @Service
2 public class UserService {
3
4 @Autowired
5 private UserRepository userRepository ;
6
7 public User getUserById ( Long id ) {
8 return userRepository . findById ( id )
9 . orElseThrow (() -> new U s e r N o t F o u n d E x c e p t i o n ( " User ␣ not ␣
found " ) ) ;
10 }
11
12 public User createUser ( User user ) {
13 // Business logic : validate email
14 if (! isValidEmail ( user . getEmail () ) ) {
15 throw new I n v a l i d E m a i l E x c e p t i o n ( " Invalid ␣ email ␣ format " ) ;
16 }
17 return userRepository . save ( user ) ;
18 }
19
20 public List < User > ge tAllAc tiveUs ers () {
21 // Business logic : filter active users
22 return userRepository . findAll ()
23 . stream ()
24 . filter ( User :: isActive )
25 . collect ( Collectors . toList () ) ;
26 }
27
6
• Transaction Management — Manage database transactions
Important Note
Service classes should NOT contain any HTTP-related code (no request/response han-
dling). They should be independent of the web layer.
1 // Mongoose model
2 const User = mongoose . model ( ’ User ’ , userSchema ) ;
3
4 // Database operations
5 const user = await User . findById ( id ) ;
6 const users = await User . find ({ active : true }) ;
7 await User . create ({ name : ’ John ’ , email : ’ john@example . com ’ }) ;
8 await User . fi ndById AndUpd ate ( id , { name : ’ Jane ’ }) ;
9 await User . fi ndById AndDel ete ( id ) ;
1 @Repository
2 public interface UserRepository extends JpaRepository < User , Long > {
3
7
6.4 Repository Features
JpaRepository Power Features
8
8
9 const User = mongoose . model ( ’ User ’ , userSchema ) ;
1 @Entity
2 @Table ( name = " users " )
3 public class User {
4
5 @Id
6 @GeneratedValue ( strategy = GenerationType . IDENTITY )
7 private Long id ;
8
9 @Column ( nullable = false )
10 private String name ;
11
12 @Column ( nullable = false , unique = true )
13 private String email ;
14
15 private Integer age ;
16
17 @Column ( columnDefinition = " boolean ␣ default ␣ true " )
18 private Boolean active ;
19
20 @CreatedDate
21 private LocalDateTime createdAt ;
22
23 // Default Constructor ( Required by JPA )
24 public User () {}
25
26 // Parameterized Constructor
27 public User ( String name , String email , Integer age ) {
28 this . name = name ;
29 this . email = email ;
30 this . age = age ;
31 }
32
33 // Getters and Setters
34 public Long getId () {
35 return id ;
36 }
37
9
53
54 public void setEmail ( String email ) {
55 this . email = email ;
56 }
57
58 public Integer getAge () {
59 return age ;
60 }
61
Annotation Description
@Entity Marks the class as a JPA entity (database table)
@Table(name = "...") Specifies the table name in database
@Id Marks the primary key field
@GeneratedValue Auto-generates ID values (auto-increment)
@Column Defines column properties (nullable, unique, etc.)
@Transient Field not persisted to database
@CreatedDate Automatically sets creation timestamp
@LastModifiedDate Automatically updates modification timestamp
@OneToMany One-to-many relationship
@ManyToOne Many-to-one relationship
@ManyToMany Many-to-many relationship
Table 4: JPA Entity Annotations
10
Important Requirement
13 // 4. Response
14 res . status (201) . json ( user ) ;
15 } catch ( error ) {
16 res . status (500) . json ({ error : error . message }) ;
17 }
18 }) ;
1 @RestController
2 @RequestMapping ( " / api / users " )
3 public class UserController {
4
5 @Autowired
6 private UserService userService ;
7
8 @PostMapping
9 public ResponseEntity < User > createUser ( @RequestBody UserDTO userDTO
) {
10 User user = userService . createUser ( userDTO ) ;
11 return ResponseEntity . status ( HttpStatus . CREATED ) . body ( user ) ;
12 }
13 }
11
1 @Service
2 public class UserService {
3
4 @Autowired
5 private UserRepository userRepository ;
6
7 public User createUser ( UserDTO userDTO ) {
8 // Business logic
9 if (! isValidEmail ( userDTO . getEmail () ) ) {
10 throw new I n v a l i d E m a i l E x c e p t i o n ( " Invalid ␣ email " ) ;
11 }
12
13 User user = new User ( userDTO . getName () , userDTO . getEmail () ) ;
14 return userRepository . save ( user ) ;
15 }
16
17 private boolean isValidEmail ( String email ) {
18 return email . contains ( " @ " ) ;
19 }
20 }
1 @Repository
2 public interface UserRepository extends JpaRepository < User , Long > {
3 // Spring provides save () , findById () , etc . automatically
4 }
1 @Entity
2 public class User {
3 @Id
4 @GeneratedValue ( strategy = GenerationType . IDENTITY )
5 private Long id ;
6 private String name ;
7 private String email ;
8
9 // Constructors , getters , setters ...
10 }
12
Aspect MERN (Express + Mon- Spring Boot
goose)
10 Learning Roadmap
10.1 Phase 1: Java Fundamentals
Java Prerequisites
• Generics
13
10.3 Phase 3: Building REST APIs
• @RestController and @RequestMapping
• Connecting to MySQL/PostgreSQL
1 // Model
2 const userSchema = new mongoose . Schema ({
3 name : String ,
4 email : String
5 }) ;
6 const User = mongoose . model ( ’ User ’ , userSchema ) ;
7
8 // Routes - Everything in one file
9 app . get ( ’/ api / users ’ , async ( req , res ) = > {
14
10 const users = await User . find () ;
11 res . json ( users ) ;
12 }) ;
13
14 app . post ( ’/ api / users ’ , async ( req , res ) = > {
15 const user = await User . create ( req . body ) ;
16 res . status (201) . json ( user ) ;
17 }) ;
18
1 @Entity
2 @Table ( name = " users " )
3 public class User {
4
5 @Id
6 @GeneratedValue ( strategy = GenerationType . IDENTITY )
7 private Long id ;
8
15 // Default Constructor
16 public User () {}
17
18 // Parameterized Constructor
19 public User ( String name , String email ) {
20 this . name = name ;
21 this . email = email ;
22 }
23
24 // Getters and Setters
25 public Long getId () { return id ; }
15
26 public void setId ( Long id ) { this . id = id ; }
27
28 public String getName () { return name ; }
29 public void setName ( String name ) { this . name = name ; }
30
31 public String getEmail () { return email ; }
32 public void setEmail ( String email ) { this . email = email ; }
33 }
1 @Repository
2 public interface UserRepository extends JpaRepository < User , Long > {
3 // JpaRepository provides all CRUD methods automatically :
4 // - save ( User user )
5 // - findById ( Long id )
6 // - findAll ()
7 // - deleteById ( Long id )
8 // - count ()
9 // - existsById ( Long id )
10
11 // Custom query methods
12 Optional < User > findByEmail ( String email ) ;
13 }
1 @Service
2 public class UserService {
3
4 @Autowired
5 private UserRepository userRepository ;
6
7 public List < User > getAllUsers () {
8 return userRepository . findAll () ;
9 }
10
11 public User getUserById ( Long id ) {
12 return userRepository . findById ( id )
13 . orElseThrow (() -> new R e s o u r c e N o t F o u n d E x c e p t i o n (
14 " User ␣ not ␣ found ␣ with ␣ id : ␣ " + id
15 ));
16 }
17
18 public User createUser ( User user ) {
19 // Business logic : Check if email already exists
20 if ( userRepository . findByEmail ( user . getEmail () ) . isPresent () ) {
21 throw new D u p l i c a t e R e s o u r c e E x c e p t i o n (
22 " User ␣ with ␣ email ␣ " + user . getEmail () + " ␣ already ␣ exists
"
23 );
24 }
25 return userRepository . save ( user ) ;
26 }
27
28 public User updateUser ( Long id , User userDetails ) {
16
29 User user = getUserById ( id ) ;
30 user . setName ( userDetails . getName () ) ;
31 user . setEmail ( userDetails . getEmail () ) ;
32 return userRepository . save ( user ) ;
33 }
34
35 public void deleteUser ( Long id ) {
36 if (! userRepository . existsById ( id ) ) {
37 throw new R e s o u r c e N o t F o u n d E x c e p t i o n (
38 " User ␣ not ␣ found ␣ with ␣ id : ␣ " + id
39 );
40 }
41 userRepository . deleteById ( id ) ;
42 }
43 }
1 @RestController
2 @RequestMapping ( " / api / users " )
3 public class UserController {
4
5 @Autowired
6 private UserService userService ;
7
8 // GET / api / users - Get all users
9 @GetMapping
10 public ResponseEntity < List < User > > getAllUsers () {
11 List < User > users = userService . getAllUsers () ;
12 return ResponseEntity . ok ( users ) ;
13 }
14
15 // GET / api / users /{ id } - Get user by ID
16 @GetMapping ( " /{ id } " )
17 public ResponseEntity < User > getUserById ( @PathVariable Long id ) {
18 User user = userService . getUserById ( id ) ;
19 return ResponseEntity . ok ( user ) ;
20 }
21
17
40 // DELETE / api / users /{ id } - Delete user
41 @DeleteMapping ( " /{ id } " )
42 public ResponseEntity < Void > deleteUser ( @PathVariable Long id ) {
43 userService . deleteUser ( id ) ;
44 return ResponseEntity . noContent () . build () ;
45 }
46 }
18
12 Configuration Files
12.1 application.properties
# Server Configuration
s e r v e r . p o r t =8080
# Database C o n f i g u r a t i o n (MySQL)
s p r i n g . d a t a s o u r c e . u r l=j d b c : mysql : / / l o c a l h o s t : 3 3 0 6 / u s e r d b
s p r i n g . d a t a s o u r c e . username=r o o t
s p r i n g . d a t a s o u r c e . password=yourpassword
# JPA C o n f i g u r a t i o n
s p r i n g . j p a . h i b e r n a t e . ddl−auto=update
s p r i n g . j p a . show−s q l=t r u e
s p r i n g . j p a . p r o p e r t i e s . h i b e r n a t e . f o r m a t s q l=t r u e
# Logging
l o g g i n g . l e v e l . o r g . s p r i n g f r a m e w o r k=INFO
l o g g i n g . l e v e l . com . yourpackage=DEBUG
13 Summary
Key Takeaways
• IoC Container manages objects — no manual object creation with new keyword
19
Learning Path Summary
14 Next Steps
Now that you understand the core concepts, here are your next steps:
20
Remember
Coming from MERN Stack, you already understand:
• Client-server architecture
These skills transfer directly to Spring Boot. The main differences are:
21