github:https://github.com/mohammedQuasimDA/smart-campus
If you:
Have doubts about any part of this guide
Find something confusing or unclear
Notice typos/errors
Please reach out in the comments/DMsβIβd be delighted to:
Clarify concepts
Fix mistakes promptly
Improve this resource for everyone
Your feedback helps make this article more accurate and helpful for future readers!
This project is a Student Management System built as a RESTful API using Spring Boot. It allows you to perform CRUD (Create, Read, Update, Delete) operations on student records, such as:
- Adding new students
- Retrieving student details
- Updating student information
- Deleting student dent records
π Getting Started
go to https://start.spring.io/ or search "spring initializr" in google
- project:maven
- language:java
- Spring boot:3.4.5 (or any version of your choice)
- Group: this is basically your company name in reverse order. like google.com-->com.google if you are individual you can just com.your_name
- Artifact: give your project an artifact name, e.g., βdemo.β
- Name: enter a name for your project, e.g., βSpringBootDemo.β
- Description: this field is optional.
- Package name: define your base package automatically generated you can also change it but it is combo of group and artifact , e.g., βcom.learning.demo.β
- Packaging: choose βJarβ for a standalone JAR file.
- java:21
Dependencies:
1. Spring Web
2. Spring data JPA
3. Mysql driver
Now click on Generate which will generate a zip ,extract it and open in IDE
My project name is smartcampus so it creates an folder with the same name
inside it you will find "src" folder under it "main" under it "java"
-->smartcampus
|->src
|->main
|->java
|->com.sc.smartcampus
|->resources
1. Understanding the Model Layer
The Model layer represents the structure of data in your application. Think of it like blueprints for the data you store in the database.
Below is the folder struct we gonna create
-->smartcampus
|->src
|->main
|->java
|->com.sc.smartcampus
|->model
|->Student.java
|->Department(enum)
|->converter
|->DepartmentConverter.java
|->resources
package com.sc.smartcampus.model;
import java.time.LocalDate;
import com.sc.smartcampus.converter.DepartmentConverter;
import com.sc.smartcampus.validation.ValidRollNumber;
import jakarta.persistence.*;
import jakarta.validation.constraints.*;
@Entity
@Table(name = "students",indexes = @Index(columnList = "rollNumber",unique = true))
public class Student {
@Id
@Column(unique = true, length = 7) // Set to maximum possible length
@ValidRollNumber
private String rollNumber;
@NotBlank(message = "Name is mandatory")
@Size(min = 2, max = 50, message = "Name must be 2-50 characters")
private String name;
@Email(message = "Invalid email format")
@Column(unique = true)
private String email;
@Column(name = "department")
@Convert(converter = DepartmentConverter.class)
private Department department;
@NotNull(message = "Enrollment date is required")
private LocalDate enrollmentDate;
//getter setter , all args and no args construtor
}
β’ @Entity: Tells Spring Boot this class represents a database table.
β’ name = "students": Sets the name of the table in the database to students.
β’ indexes = @Index(...): Creates a database index on the rollNumber column to speed up search queries and enforce uniqueness.
β’ unique = true: Ensures that no two students can have the same roll number.
β’ @id: Marks this field as the primary key (unique identifier).
β’ @column: Configures the database column.
β’ unique = true: Ensures no two rows can have the same value.
β’ length = 7: Limits the max characters to 7 (for example, 22BCS01).
β’ @ValidRollNumber:custom validation annotation // will show
β’ @NotBlankEnsures that the field is not null or empty
β’ @Size:Ensures that the name is between 2 and 50 characters long
β’ @Email:Makes sure the email field is a valid email address (like [email protected])
β’ @column(name = "department"): Creates a column named "department"
β’ @Convert(...): Uses a custom converter (here, DepartmentConverter) to convert the Department enum to a code like "CS" and vice versa.//will show
package com.sc.smartcampus.model;
public enum Department {
// Core Engineering
AEROSPACE("AE", "Aerospace Engineering"),
AUTOMOBILE("AU", "Automobile Engineering"),
BIOTECH("BT", "Biotechnology"),
CHEMICAL("CH", "Chemical Engineering"),
CIVIL("CE", "Civil Engineering"),
COMPUTER_SCIENCE("CS", "Computer Science"),
COMPUTER_ENGINEERING("CSE", "Computer Science Engineering"),
ELECTRICAL("EE", "Electrical Engineering"),
ELECTRONICS("EC", "Electronics Engineering"),
ELECTRONICS_COMMUNICATION("ECE", "Electronics and Communication"),
ENVIRONMENTAL("EN", "Environmental Engineering"),
INDUSTRIAL("IE", "Industrial Engineering"),
INFORMATION_TECH("IT", "Information Technology"),
INSTRUMENTATION("IC", "Instrumentation and Control"),
MECHANICAL("ME", "Mechanical Engineering"),
MECHATRONICS("MT", "Mechatronics"),
METALLURGY("ML", "Metallurgical Engineering"),
MINING("MN", "Mining Engineering"),
PETROLEUM("PE", "Petroleum Engineering"),
PRODUCTION("PD", "Production Engineering"),
ROBOTICS("RB", "Robotics Engineering"),
TEXTILE("TE", "Textile Engineering"),
ARTIFICIAL_INTELLIGENCE("AI", "Artificial Intelligence"),
DATA_SCIENCE("DS", "Data Science"),
CYBER_SECURITY("CY", "Cyber Security"),
CLOUD_COMPUTING("CC", "Cloud Computing"),
IOT("IO", "Internet of Things");
private final String code;
private final String fullName;
Department(String code, String fullName) {
this.code = code;
this.fullName = fullName;
}
public String getCode() {
return code;
}
public String getFullName() {
return fullName;
}
// Helper method to get department from code
public static Department fromCode(String code) {
for (Department dept : values()) {
if (dept.code.equalsIgnoreCase(code)) {
return dept;
}
}
throw new IllegalArgumentException("Invalid department code: " + code);
}
}
This class is a Java enum (enumeration) called Department, and it's used to define a fixed list of engineering departments along with a short code and full name for each one
Purpose of Department enum
This enum helps you:
1. Store departments using short codes like "CS" or "ME" in the database.
2. Show full names like "Computer Science" or "Mechanical Engineering" in the UI.
β’ code: Short version like "CS" or "ME".
β’ fullName: Full readable name like "Computer Science"
fromCode() Method convert a code (like "ME") back into an MECHANICAL:
package com.sc.smartcampus.converter;
import com.sc.smartcampus.model.Department;
import jakarta.persistence.AttributeConverter;
import jakarta.persistence.Converter;
@Converter(autoApply = true)
public class DepartmentConverter implements AttributeConverter<Department, String> {
@Override
public String convertToDatabaseColumn(Department department) {
if (department == null) return null;
return department.getCode(); // store "ME" instead of "MECHANICAL"
}
@Override
public Department convertToEntityAttribute(String code) {
if (code == null) return null;
return Department.fromCode(code); // convert "ME" back to MECHANICAL
}
}
Converter
Problem It Solves
By default, if you use an enum in a JPA entity (like Department department in Student), it will store it in the database either as:
β’ The ordinal (position number, like 0, 1, 2) β not readable.
β’ Or the enum name (like "MECHANICAL").
But you want to store the short code instead, like "ME" or "CS". Why?
β
It's compact
β
It's readable
β
It's customized to your preference ("CS" instead of "COMPUTER_SCIENCE")
To do this, we use a custom converter with JPA: DepartmentConverter.
@Converter(autoApply = true)
Automatically use this converter for any Department type in your entity classes
AttributeConverter
will convert between the Department enum (Java side) and a String (DB side)
validation
-->smartcampus
|->src
|->main
|->java
|->com.sc.smartcampus
|->model
|->converter
|->validation
|->RollNumberValidator.java
|->ValidRollNumber(@interface)
|->resources
In our model we have @ValidRollNumber for private String rollNumber; which was a custome
What We're Doing Here
We're creating a custom validation annotation that checks if a roll number:
1. Follows the correct pattern like 23CS001 (2-digit year + department code + 3 digits)
2. Has a valid department code like CS, ME, EC, etc.
@Documented
@Constraint(validatedBy = RollNumberValidator.class)
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidRollNumber {
String message() default "Invalid roll number or department code";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
β’ @Constraint: This tells Spring which validator class will handle this annotation (in our case, RollNumberValidator).
β’ @Target(ElementType.FIELD): Can be used on fields.
β’ @Retention(RUNTIME): The annotation should be available at runtime.
String message() default "Invalid roll number or department code";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
are required parts of every custom validation annotation in Spring Boot (using Jakarta Bean Validation).
package com.sc.smartcampus.validation;
import com.sc.smartcampus.model.Department;
import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;
public class RollNumberValidator implements ConstraintValidator<ValidRollNumber, String> {
@Override
public boolean isValid(String rollNumber, ConstraintValidatorContext context) {
if (rollNumber == null || !rollNumber.matches("^\\d{2}[A-Z]{1,2}\\d{3}$")) {
return false; // format is invalid
}
// extract department code
String deptCode = rollNumber.substring(2, rollNumber.length() - 3);
try {
Department.fromCode(deptCode); // checks if dept code is valid
return true;
} catch (IllegalArgumentException e) {
return false;
}
}
}
public class RollNumberValidator implements ConstraintValidator-->
β’ This is a custom validator class for the annotation @ValidRollNumber.
β’ It tells Spring how to validate a String field (like a roll number).
β’ ConstraintValidator: Here, A = ValidRollNumber (custom annotation), and T = String (type of the field being validated).
rollNumber.substring(2, rollNumber.length() - 3);-->it takes only the code from the pattern 21ME093-->ME
2. Repository Layer
In Spring Boot, the repository layer is used to interact with the database. It contains the code to save, find, delete, or update data.
Spring Data JPA makes this super simple β you donβt need to write SQL for common tasks!
-->smartcampus
|->src
|->main
|->java
|->com.sc.smartcampus
|->model
|->converter
|->validation
|->repository
|-> StudentRepository
|->resources
package com.sc.smartcampus.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.sc.smartcampus.model.Student;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import java.util.List;
public interface StudentRepository extends JpaRepository<Student, String> {
@Query("SELECT MAX(s.rollNumber) FROM Student s WHERE s.rollNumber LIKE :pattern")
String findMaxRollNumberByPattern(@Param("pattern") String pattern);
@Query("SELECT s FROM Student s WHERE LOWER(s.name) LIKE LOWER(CONCAT('%', :keyword, '%')) " +
"OR LOWER(s.email) LIKE LOWER(CONCAT('%', :keyword, '%')) " +
"OR LOWER(s.rollNumber) LIKE LOWER(CONCAT('%', :keyword, '%'))")
List<Student> searchByKeyword(@Param("keyword") String keyword);
}
-->The
here JPA give you many querys like findById() etc.
but sometime we need custom queries like to get maximum roll number
@Query("SELECT MAX(s.rollNumber) FROM Student s WHERE s.rollNumber LIKE :pattern")
String findMaxRollNumberByPattern(@Param("pattern") String pattern);
String pattern -->it wil have a pattern[17ME204] which user passes
so what we do is that we search the DB with the same pattern and find the highest roll number.
When adding a new student, you might want to auto-generate the next roll number based on a pattern
@Query("SELECT s FROM Student s WHERE LOWER(s.name) LIKE LOWER(CONCAT('%', :keyword, '%')) " +
"OR LOWER(s.email) LIKE LOWER(CONCAT('%', :keyword, '%')) " +
"OR LOWER(s.rollNumber) LIKE LOWER(CONCAT('%', :keyword, '%'))")
List<Student> searchByKeyword(@Param("keyword") String keyword);
Allows you to search students by name, email, or roll number β case-insensitive and partial match
3. DTOs (Data Transfer Objects)
A DTO (Data Transfer Object) is a simple Java class used to transfer data between the frontend and backend.
We use DTOs to:
β’ Control what data is exposed to clients.
β’ Separate internal entity logic from external data exchange.
β’ Apply input validation rules cleanly.
-->smartcampus
|->src
|->main
|->java
|->com.sc.smartcampus
|->model
|->converter
|->validation
|->repository
|->dto
|-> StudentRequestDTO
|-> StudentResponseDTO
|->resources
StudentRequestDTO β When client sends data to backend (POST/PUT)
package com.sc.smartcampus.dto;
import jakarta.validation.constraints.Email;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import jakarta.validation.constraints.Size;
import java.time.LocalDate;
public class StudentRequestDTO {
@NotBlank(message = "Name is required")
@Size(min = 2, max = 50, message = "Name must be between 2 and 50 characters")
private String name;
@Email(message = "Invalid email format")
@NotBlank(message = "Email is required")
private String email;
@NotBlank(message = "Department code is required")
private String department;
@NotNull(message = "Enrollment date is required")
private LocalDate enrollmentDate;
public StudentRequestDTO() {
}
public StudentRequestDTO(String name, String email, String department, LocalDate enrollmentDate) {
this.name = name;
this.email = email;
this.department = department;
this.enrollmentDate = enrollmentDate;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
public LocalDate getEnrollmentDate() {
return enrollmentDate;
}
public void setEnrollmentDate(LocalDate enrollmentDate) {
this.enrollmentDate = enrollmentDate;
}
}
β’ @notblank: Field cannot be empty or only spaces.
β’ @Size(min, max): Limits name length.
StudentResponseDTO
When backend sends data to client (GET)
Purpose:
This DTO is used when the backend sends student data to the frontend. It contains:
β’ The generated roll number
β’ Both department code (CS) and full name (Computer Science)
β’ All other student info
package com.sc.smartcampus.dto;
import java.time.LocalDate;
public class StudentResponseDTO {
private String rollNumber;
private String name;
private String email;
private String department; // e.g., "CS"
private String departmentFullName; // e.g., "Computer Science"
private LocalDate enrollmentDate;
public StudentResponseDTO() {
}
public StudentResponseDTO(String rollNumber, String name, String email,
String department, String departmentFullName,
LocalDate enrollmentDate) {
this.rollNumber = rollNumber;
this.name = name;
this.email = email;
this.department = department;
this.departmentFullName = departmentFullName;
this.enrollmentDate = enrollmentDate;
}
public String getRollNumber() {
return rollNumber;
}
public void setRollNumber(String rollNumber) {
this.rollNumber = rollNumber;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getEmail() {
return email;
}
public void setEmail(String email) {
this.email = email;
}
public String getDepartment() {
return department;
}
public void setDepartment(String department) {
this.department = department;
}
public String getDepartmentFullName() {
return departmentFullName;
}
public void setDepartmentFullName(String departmentFullName) {
this.departmentFullName = departmentFullName;
}
public LocalDate getEnrollmentDate() {
return enrollmentDate;
}
public void setEnrollmentDate(LocalDate enrollmentDate) {
this.enrollmentDate = enrollmentDate;
}
}
Service
What is a Service Interface?
In Spring Boot, the service layer is where:
β’ Core business logic is written
β’ The controller sends requests here
β’ The repository is called from here to talk to the database
-->smartcampus
|->src
|->main
|->java
|->com.sc.smartcampus
|->model
|->converter
|->validation
|->repository
|->dto
|->service
|->impl
|->StudentServiceImpl.java
|->StudentService(interface)
|->resources
package com.sc.smartcampus.service;
import com.sc.smartcampus.dto.StudentRequestDTO;
import com.sc.smartcampus.dto.StudentResponseDTO;
import java.util.List;
public interface StudentService {
StudentResponseDTO createStudent(StudentRequestDTO dto);
StudentResponseDTO getStudentByRollNumber(String rollNumber);
StudentResponseDTO updateStudent(String rollNumber, StudentRequestDTO dto);
void deleteStudent(String rollNumber);
List<StudentResponseDTO> getAllStudents();
List<StudentResponseDTO> searchStudents(String keyword);
String generateNextRollNumber(String year, String departmentCode);
}
What Is StudentServiceImpl?
β’ It implements the methods defined in your StudentService interface.
β’ Handles all business logic: creating, updating, deleting, searching, and managing roll numbers.
β’ Talks to the repository (StudentRepository) to interact with the database.
β’ Converts data between the DTOs and Entity classes.
private StudentRepository studentRepository;
public StudentServiceImpl(StudentRepository studentRepository) {
this.studentRepository = studentRepository;
}
To use/access the repository
package com.sc.smartcampus.service.impl;
import com.sc.smartcampus.dto.StudentRequestDTO;
import com.sc.smartcampus.dto.StudentResponseDTO;
import com.sc.smartcampus.model.Department;
import com.sc.smartcampus.model.Student;
import com.sc.smartcampus.repository.StudentRepository;
import com.sc.smartcampus.service.StudentService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.time.format.DateTimeFormatter;
import java.util.List;
import java.util.stream.Collectors;
@Service
public class StudentServiceImpl implements StudentService {
private StudentRepository studentRepository;
public StudentServiceImpl(StudentRepository studentRepository) {
this.studentRepository = studentRepository;
}
private StudentResponseDTO mapToResponseDTO(Student student) {
StudentResponseDTO dto = new StudentResponseDTO();
dto.setRollNumber(student.getRollNumber());
dto.setName(student.getName());
dto.setEmail(student.getEmail());
dto.setDepartment(student.getDepartment().getCode());
dto.setDepartmentFullName(student.getDepartment().getFullName());
dto.setEnrollmentDate(student.getEnrollmentDate());
return dto;
}
// Implement all methods here...
@Override
public StudentResponseDTO createStudent(StudentRequestDTO dto) {
// 1. Convert department code string to enum (throws exception if invalid)
Department department = Department.fromCode(dto.getDepartment());
// 2. Generate the year part from enrollment date
String year = String.valueOf(dto.getEnrollmentDate().getYear()).substring(2); // last two digits, e.g. "23"
// 3. Generate the next roll number for this year + department
String nextRollNumber = generateNextRollNumber(year, department.getCode());
// 4. Create new Student entity
Student student = new Student();
student.setRollNumber(nextRollNumber);
student.setName(dto.getName());
student.setEmail(dto.getEmail());
student.setDepartment(department);
student.setEnrollmentDate(dto.getEnrollmentDate());
// 5. Save student entity
student = studentRepository.save(student);
// 6. Convert to response DTO and return
return mapToResponseDTO(student);
}
@Override
public StudentResponseDTO getStudentByRollNumber(String rollNumber) {
Student student = studentRepository.findById(rollNumber)
.orElseThrow(() -> new RuntimeException("Student not found with roll number: " + rollNumber));
return mapToResponseDTO(student);
}
@Override
public StudentResponseDTO updateStudent(String rollNumber, StudentRequestDTO dto) {
// 1. Fetch the existing student by rollNumber
Student student = studentRepository.findById(rollNumber)
.orElseThrow(() -> new RuntimeException("Student not found with roll number: " + rollNumber));
// 2. Update the fields from the DTO (except rollNumber, which is immutable)
student.setName(dto.getName());
student.setEmail(dto.getEmail());
// 3. Convert and update department (validate department code)
Department department = Department.fromCode(dto.getDepartment());
student.setDepartment(department);
// 4. Update enrollment date
student.setEnrollmentDate(dto.getEnrollmentDate());
// 5. Save the updated student
student = studentRepository.save(student);
// 6. Convert to response DTO and return
return mapToResponseDTO(student);
}
@Override
public void deleteStudent(String rollNumber) {
// Check if student exists, else throw exception
Student student = studentRepository.findById(rollNumber)
.orElseThrow(() -> new RuntimeException("Student not found with roll number: " + rollNumber));
// Delete the student
studentRepository.delete(student);
}
@Override
public List<StudentResponseDTO> getAllStudents() {
List<Student> students = studentRepository.findAll();
return students.stream()
.map(this::mapToResponseDTO)
.collect(Collectors.toList());
}
@Override
public List<StudentResponseDTO> searchStudents(String keyword) {
List<Student> students = studentRepository.searchByKeyword(keyword);
return students.stream()
.map(this::mapToResponseDTO)
.collect(Collectors.toList());
}
@Override
public String generateNextRollNumber(String year, String departmentCode) {
// 1. Create the pattern to find max existing roll numbers for the year+dept
// Example pattern: "21CS%" to match roll numbers starting with 21CS
String pattern = year + departmentCode + "%";
// 2. Get the max existing roll number with this pattern from DB
String maxRollNumber = studentRepository.findMaxRollNumberByPattern(pattern);
int nextSerial = 1; // default if no existing roll numbers
if (maxRollNumber != null) {
// Extract the last 3 digits of the roll number (serial number)
String serialStr = maxRollNumber.substring(maxRollNumber.length() - 3);
try {
int serialNum = Integer.parseInt(serialStr);
nextSerial = serialNum + 1;
} catch (NumberFormatException e) {
// fallback if parsing fails, start from 1
nextSerial = 1;
}
}
// 3. Format the serial to be 3 digits with leading zeros (e.g., 001, 042)
String serialFormatted = String.format("%03d", nextSerial);
// 4. Build and return the next roll number string
return year + departmentCode + serialFormatted;
}
// You can add private helper methods if needed, for example, a mapper from Student to DTO
}
createStudent(StudentRequestDTO dto)
Converts StudentRequestDTO β Student β StudentResponseDTO
Steps:
1. Converts department string to a valid Department enum using Department.fromCode().
2. Extracts year from enrollment date (e.g., 2023 β "23").
3. Generates the next available roll number like 23CS001.
4. Creates and saves a Student entity.
5. Converts entity to response DTO.
getStudentByRollNumber(String rollNumber)
β’ Finds a student using studentRepository.findById(...).
β’ Throws a RuntimeException if not found.
β’ Returns a StudentResponseDTO
updateStudent(String rollNumber, StudentRequestDTO dto)
Steps:
1. Fetch existing student.
2. Update fields except roll number.
3. Validate department again using fromCode.
4. Save and return updated StudentResponseDTO
deleteStudent(String rollNumber)
β’ Checks if student exists.
β’ Deletes using studentRepository.delete()
getAllStudents()
β’ Fetches all students.
β’ Maps each entity to a StudentResponseDTO
searchStudents(String keyword)
β’ Uses a custom query to search by name, email, or roll number.
β’ Converts results to DTOs.
generateNextRollNumber(String year, String departmentCode)
Logic:
1. Constructs a search pattern like 23CS%.
2. Finds the current highest roll number matching the pattern.
3. Extracts the last 3 digits β increments β formats to 3 digits (e.g., 003).
4. Returns the new roll number: e.g., 23CS004
mapToResponseDTO
β’ Converts a Student entity into a readable API-friendly response object (StudentResponseDTO).
β’ Useful to prevent exposing internal entity structure.
Controller
-->smartcampus
|->src
|->main
|->java
|->com.sc.smartcampus
|->model
|->converter
|->validation
|->repository
|->dto
|->service
|-controller
|->StudentController
|->resources
Purpose of StudentController
This class handles all HTTP requests related to the Student resource. It's part of the Controller layer in a Spring Boot application, which connects the client (frontend/API consumer) to the Service layer.
Youβre using:
β’ @RestController β to mark this class as a REST controller.
@RequestMapping("/api/students") β so all routes start with /api/students
package com.sc.smartcampus.controller;
import com.sc.smartcampus.dto.StudentRequestDTO;
import com.sc.smartcampus.dto.StudentResponseDTO;
import com.sc.smartcampus.service.StudentService;
import jakarta.validation.Valid;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.List;
@RestController
@RequestMapping("/api/students")
public class StudentController {
@Autowired
private StudentService studentService;
// 1. Create Student
@PostMapping
public ResponseEntity<StudentResponseDTO> createStudent(@Valid @RequestBody StudentRequestDTO dto) {
StudentResponseDTO created = studentService.createStudent(dto);
return ResponseEntity.ok(created);
}
// 2. Get Student by Roll Number
@GetMapping("/{rollNumber}")
public ResponseEntity<StudentResponseDTO> getStudentByRollNumber(@PathVariable String rollNumber) {
StudentResponseDTO student = studentService.getStudentByRollNumber(rollNumber);
return ResponseEntity.ok(student);
}
// 3. Update Student by Roll Number
@PutMapping("/{rollNumber}")
public ResponseEntity<StudentResponseDTO> updateStudent(@PathVariable String rollNumber,
@Valid @RequestBody StudentRequestDTO dto) {
StudentResponseDTO updated = studentService.updateStudent(rollNumber, dto);
return ResponseEntity.ok(updated);
}
// 4. Delete Student by Roll Number
@DeleteMapping("/{rollNumber}")
public ResponseEntity<Void> deleteStudent(@PathVariable String rollNumber) {
studentService.deleteStudent(rollNumber);
return ResponseEntity.noContent().build();
}
// 5. Get All Students
@GetMapping
public ResponseEntity<List<StudentResponseDTO>> getAllStudents() {
List<StudentResponseDTO> students = studentService.getAllStudents();
return ResponseEntity.ok(students);
}
// 6. Search Students by keyword
@GetMapping("/search")
public ResponseEntity<List<StudentResponseDTO>> searchStudents(@RequestParam String keyword) {
List<StudentResponseDTO> results = studentService.searchStudents(keyword);
return ResponseEntity.ok(results);
}
}
β’ @PostMapping β handles POST /api/students.
β’ @RequestBody β reads JSON body into a Java object.
β’ @valid β triggers validation (e.g., @notblank, @ValidRollNumber).
β’ Returns ResponseEntity.ok(...) with the saved student data
β’ @GetMapping("/{rollNumber}") β dynamic path parameter.
β’ @PathVariable β binds the rollNumber from the URL
β’ @PutMapping("/{rollNumber}")-used to update a full resource
β’ @DeleteMapping("/{rollNumber}")-delte a resource
β’ @RequestParam is used for query parameters like /api/students/search?keyword=john
Connect to Database
-->smartcampus
|->src
|->main
|->java
|->com.sc.smartcampus
|->model
|->converter
|->validation
|->repository
|->dto
|->service
|-controller
|->resources
|->application.properties
spring.datasource.url=jdbc:mysql://localhost:3306/database_name
spring.datasource.username=username
spring.datasource.password=password
spring.datasource.driver-class-name=com.mysql.cj.jdbc.Driver
spring.jpa.database-platform=org.hibernate.dialect.MySQL8Dialect
spring.jpa.show-sql=true
spring.jpa.hibernate.ddl-auto=update
server.port=9090--> i used port 9090 by default it is 8080
We have create the spring boot app now run and pass api via postman
if you are using default port change 9090 to 8080
POST http://localhost:9090/api/students
Content-Type: application/json
{
"name": "Joqsadhn a Doe",
"email": "[email protected]",
"department": "CS",
"enrollmentDate": "2023-08-15"
}
GET http://localhost:9090/api/students
GET http://localhost:9090/api/students/23CS001
DELETE http://localhost:9090/api/students/21CS001
GET http://localhost:9090/api/students/search?keyword=john
PUT http://localhost:9090/api/students/23CS001
Content-Type: application/json
{
"name": "John Doe Updated",
"email": "[email protected]",
"department": "ME",
"enrollmentDate": "2023-08-20"
}
Top comments (0)