Closed mohammad-fahs closed 1 week ago
,.
spring.datasource.url=jdbc:mysql://localhost:3306/student_management spring.datasource.username=root spring.datasource.password=admin spring.jpa.hibernate.ddl-auto=update spring.jpa.show-sql=true
@Entity @Getter @Setter public class Student { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) Long id; String firstName; String lastName; String email; int age; @OneToMany Enrollment enrollments; public Student(String firstName,String lastName,int age ,String email) { this.id = Long.valueOf(UUID.randomUUID().toString()); this.firstName = firstName; this.lastName=lastName; this.email = email; this.age=age; this.enrollments= new Enrollment(); } }
@Entity
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
Long id;
@ManyToOne
Optional
@Entity @Getter @Setter @AllArgsConstructor @NoArgsConstructor public class Course { @Id @GeneratedValue(strategy = GenerationType.IDENTITY) Long id; String courseName; String courseCode; String instructor; int credits; @OneToMany Enrollment enrollments; public Course(String courseName, String courseCode, String instructor, int credits) { this.courseName = courseName; this.courseCode = courseCode; this.instructor = instructor; this.credits = credits; this.enrollments = new Enrollment(); } }
import java.time.LocalDateTime;
public class ApiResponse
import jakarta.persistence.UniqueConstraint; import jakarta.validation.constraints.NotBlank; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @Setter @getter @NoArgsConstructor @AllArgsConstructor public class CreateCourseDTO { @notblank String courseName; @notblank String courseCode; @notblank String instructor; int credits; }
import jakarta.validation.constraints.NotBlank; import lombok.AllArgsConstructor; import lombok.Getter; import lombok.NoArgsConstructor; import lombok.Setter; @Setter @Getter @NoArgsConstructor @AllArgsConstructor public class UpdateCourseDTO { @NotBlank String courseName; @NotBlank String courseCode; @NotBlank String instructor; int credits; }
mport lombok.NoArgsConstructor; import lombok.Setter; @Setter @Getter @NoArgsConstructor @AllArgsConstructor public class CreateStudentDTO { @NotBlank @Size(min = 2, message = "firstName should have at least 2 characters") String firstName; @NotBlank @Size(min = 2, message = "lastName should have at least 2 characters") String lastName; @Positive int age; @NotBlank @Email(message = "Email should be valid") String email; }
@Setter @Getter @NoArgsConstructor @AllArgsConstructor public class UpdateStudentDTO { @NotBlank @Size(min = 2, message = "firstName should have at least 2 characters") String firstName;
@NotBlank
@Size(min = 2, message = "lastName should have at least 2 characters")
String lastName;
@Positive
int age;
@NotBlank
@Email(message = "Email should be valid")
String email;
}
import java.util.Date;
@Setter @Getter @NoArgsConstructor @AllArgsConstructor public class EnrollStudentINCourse { @NotBlank Long studentId; @NotBlank Long courseId; Date enrollmentDate;
@Pattern(regexp = "A|B|C|D|F", message = "Grade must be A, B,C,D, or F")
String grade;
}
@Setter @Getter @NoArgsConstructor @AllArgsConstructor public class UpdateEnrollmentDTO { Student s; Course c; Date enrollmentDate; @Pattern(regexp = "A|B|C|D|F", message = "Grade must be A, B,C,D, or F") String grade; }
@Autowired
StudentRepository studentRepository;
public final List<Student> students= new ArrayList<Student>();
public Stutent createStudent(CreateStudentDTO studentDTO){
Student student= new Student(studentDTO.getFirstName(),studentDTO.getLastName(),studentDTO.getAge(),studentDTO.getEmail());
students.add(student);
return student;
}
public List<Student> getAllStudent(){
return students;
}
public Optional<Student> getStudentById(Long id){
Optional<Student> student= studentRepository.findById(id);
return student;
}
public Student updateStudent(Long id, UpdateStudentDTO updatedStudent) {
Optional<Student> existingStudentOptional = studentRepository.findById(id);
if (existingStudentOptional.isPresent()) {
Student existingStudent = existingStudentOptional.get();
existingStudent.setFirstName(updatedStudent.getFirstName());
existingStudent.setLastName(updatedStudent.getLastName());
existingStudent.setAge(updatedStudent.getAge());
existingStudent.setEmail(updatedStudent.getEmail());
return studentRepository.save(existingStudent);
} else {
return null;
}
}
public void deleteStudent(Long id){
studentRepository.deleteById(id);
}
}
@Autowired
public CourseRepository courseRepository;
public final List<Course> courses= new ArrayList<Course>();
public Course createCourse(CreateCourseDTO courseDTO){
Course course= new Course(courseDTO.getCourseName(),courseDTO.getCourseCode(),courseDTO.getInstructor(),courseDTO.getCredits());
courses.add(course);
return course;
}
public List<Course> getAllCourses(){
return courses;
}
public Optional<Course> getCourseById(Long id){
Optional<Course> course= courseRepository.findById(id);
if(course!=null)
return course;
return null;
}
public Course updateCourse(Long id, UpdateCourseDTO updatedCourse) {
Optional<Course> existingCourseOptional = courseRepository.findById(id);
if (existingCourseOptional.isPresent()) {
Course existingCourse = existingCourseOptional.get();
existingCourse.setCourseName(updatedCourse.getCourseName());
existingCourse.setInstructor(updatedCourse.getInstructor());
existingCourse.setCourseCode(updatedCourse.getCourseCode());
existingCourse.setCredits(updatedCourse.getCredits());
return courseRepository.save(existingCourse);
} else {
return null;
}
}
public void deleteCourse(Long id){
courseRepository.deleteById(id);
}
}
@Autowired
public EnrollmentRepository enrollmentRepository;
@Autowired
public StudentRepository studentRepository;
@Autowired
public CourseRepository courseRepository;
public Enrollment enrollStudentInACourse(Long studentId, Long courseId, Date enrollmentDate, String grade) {
Optional<Student> student= studentRepository.findById(studentId);
Optional<Course> course=courseRepository.findById(courseId);
Enrollment enrollment= new Enrollment(student,course,enrollmentDate,grade);
return enrollment;
}
public List<Enrollment> getAllEnrollments(){
return enrollmentRepository.findAll();
}
public Optional<Enrollment> getEnrollmentForStudent(Long studentId){
Optional<Enrollment> enrollment= enrollmentRepository.findByStudentId(studentId);
return enrollment;
}
public Optional<Enrollment> getEnrollmentForCourse(Long courseId){
Optional<Enrollment> enrollment= enrollmentRepository.findByCourseId(courseId);
return enrollment;
}
public void deleteEnrollment(Long id){
enrollmentRepository.deleteById(id);
}
public Enrollment updateEnrollment(Long id, UpdateEnrollmentDTO updatedEnrollment) {
Optional<Enrollment> existingEnrollmentOptional = enrollmentRepository.findById(id);
if (existingEnrollmentOptional.isPresent()) {
Enrollment existingEnrollment= existingEnrollmentOptional.get();
existingEnrollment.setStudent(Optional.ofNullable(updatedEnrollment.getS()));
existingEnrollment.setCourse(Optional.ofNullable(updatedEnrollment.getC()));
existingEnrollment.setEnrollmentDate(updatedEnrollment.getEnrollmentDate());
existingEnrollment.setGrade(updatedEnrollment.getGrade());
return enrollmentRepository.save(existingEnrollment);
} else {
return null;
}
}
}
import jakarta.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime; import java.util.List; import java.util.Optional;
@RestController @RequestMapping("/api/courses") public class CourseController {
@Autowired
private CourseService courseService;
@PostMapping
public ResponseEntity<ApiResponse<Course>> createCourse (@Valid @RequestBody CreateCourseDTO courseDTO){
try {
Course createdCourse = courseService.createCourse(courseDTO);
return ResponseEntity.status(HttpStatus.CREATED)
.body(new ApiResponse<>(true, createdCourse, "Course created successfully", HttpStatus.CREATED.value(), LocalDateTime.now()));
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(new ApiResponse<>(false, null, "Failed to create Course : " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value(),LocalDateTime.now()));
}
}
@GetMapping
public ResponseEntity<ApiResponse<List<Course>>> getAllCourses() {
try {
List<Course> courses = courseService.getAllCourses();
return ResponseEntity.status(HttpStatus.CREATED)
.body(new ApiResponse<>(true, courses, "courses listed succesfully", HttpStatus.CREATED.value(), LocalDateTime.now()));
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(new ApiResponse<>(false, null, "Failed to list courses: " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value(), LocalDateTime.now()));
}
}
@GetMapping("/{id}")
public ResponseEntity<ApiResponse<Optional<Course>>> getCourseById(@PathVariable Long id) {
try {
Optional<Course> course = courseService.getCourseById(id);
if (course != null) {
return ResponseEntity.ok(new ApiResponse<>(true, course, "course retrieved successfully", HttpStatus.OK.value(), LocalDateTime.now()));
} else {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(new ApiResponse<>(false, null, "course not found", HttpStatus.NOT_FOUND.value(), LocalDateTime.now()));
}
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(new ApiResponse<>(false, null, "Failed to retrieve course : " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value(), LocalDateTime.now()));
}
}
@PutMapping("/{id}")
public ResponseEntity<ApiResponse<Course>> updateCourse(@PathVariable Long id,@Valid @RequestBody UpdateCourseDTO courseToBeUpdated){
try {
Course course = courseService.updateCourse(id, courseToBeUpdated);
if (course != null) {
return ResponseEntity.ok(new ApiResponse<>(true, course, "course updated successfully", HttpStatus.OK.value(),LocalDateTime.now()));
} else {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(new ApiResponse<>(false, null, "course not found", HttpStatus.NOT_FOUND.value(),LocalDateTime.now()));
}
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(new ApiResponse<>(false, null, "Failed to update course: " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value(),LocalDateTime.now()));
}
}
@DeleteMapping("/{id}")
public ResponseEntity<ApiResponse<Void>> deleteCourse(@PathVariable Long id) {
try {
courseService.deleteCourse(id);
return ResponseEntity.ok(new ApiResponse<>(true, null, "course deleted successfully", HttpStatus.OK.value(),LocalDateTime.now()));
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(new ApiResponse<>(false, null, "Failed to delete course: " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value(),LocalDateTime.now()));
}
}
}
import jakarta.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime; import java.util.List; import java.util.Optional;
@RestController @RequestMapping("/api/students") public class StudentController { @Autowired private StudentService studentService;
@PostMapping
public ResponseEntity<ApiResponse<Student>> createStudent(@Valid @RequestBody CreateStudentDTO studentDTO){
try {
Student createdStudent = studentService.createStudent(studentDTO);
return ResponseEntity.status(HttpStatus.CREATED)
.body(new ApiResponse<>(true, createdStudent, "Student created successfully", HttpStatus.CREATED.value(), LocalDateTime.now()));
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(new ApiResponse<>(false, null, "Failed to create student: " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value(),LocalDateTime.now()));
}
}
@GetMapping
public ResponseEntity<ApiResponse<List<Student>>> getAllStudents() {
try {
List<Student> students = studentService.getAllStudent();
return ResponseEntity.status(HttpStatus.CREATED)
.body(new ApiResponse<>(true, students, "Student listed succesfully", HttpStatus.CREATED.value(), LocalDateTime.now()));
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(new ApiResponse<>(false, null, "Failed to list students: " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value(), LocalDateTime.now()));
}
}
@GetMapping("/{id}")
public ResponseEntity<ApiResponse<Optional<Student>>> getStudentById(@PathVariable Long id) {
try {
Optional<Student> student = studentService.getStudentById(id);
if (student != null) {
return ResponseEntity.ok(new ApiResponse<>(true, student, "Student retrieved successfully", HttpStatus.OK.value(), LocalDateTime.now()));
} else {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(new ApiResponse<>(false, null, "Student not found", HttpStatus.NOT_FOUND.value(), LocalDateTime.now()));
}
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(new ApiResponse<>(false, null, "Failed to retrieve student: " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value(), LocalDateTime.now()));
}
}
@PutMapping("/{id}")
public ResponseEntity<ApiResponse<Student>> updateStudent(@PathVariable Long id,@Valid @RequestBody UpdateStudentDTO studentToBeUpdated){
try {
Student student = studentService.updateStudent(id, studentToBeUpdated);
if (student != null) {
return ResponseEntity.ok(new ApiResponse<>(true, student, "Student updated successfully", HttpStatus.OK.value(),LocalDateTime.now()));
} else {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(new ApiResponse<>(false, null, "Student not found", HttpStatus.NOT_FOUND.value(),LocalDateTime.now()));
}
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(new ApiResponse<>(false, null, "Failed to update student: " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value(),LocalDateTime.now()));
}
}
@DeleteMapping("/{id}")
public ResponseEntity<ApiResponse<Void>> deleteStudent(@PathVariable Long id) {
try {
studentService.deleteStudent(id);
return ResponseEntity.ok(new ApiResponse<>(true, null, "Student deleted successfully", HttpStatus.OK.value(),LocalDateTime.now()));
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(new ApiResponse<>(false, null, "Failed to delete student: " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value(),LocalDateTime.now()));
}
}
} Enrollment Controller
import com.Jinan.Task4.DTO.ApiResponse; import com.Jinan.Task4.DTO.request.EnrollStudentINCourse; import com.Jinan.Task4.DTO.request.UpdateEnrollmentDTO; import com.Jinan.Task4.DTO.request.UpdateStudentDTO; import com.Jinan.Task4.Service.EnrollmentService; import com.Jinan.Task4.model.Enrollment; import com.Jinan.Task4.model.Student; import jakarta.validation.Valid; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.web.bind.annotation.*;
import java.time.LocalDateTime; import java.util.List; import java.util.Optional;
@RestController @RequestMapping("/api/enrollments") public class EnrollmentController { @Autowired private EnrollmentService enrollmentService;
@PostMapping
public ResponseEntity<ApiResponse<Enrollment>> enrollStudentInACourse(@Valid @RequestBody EnrollStudentINCourse enrollStudent){
try {
Enrollment enrollment = enrollmentService.enrollStudentInACourse(enrollStudent.getStudentId(), enrollStudent.getCourseId(), enrollStudent.getEnrollmentDate(), enrollStudent.getGrade());
return ResponseEntity.ok(new ApiResponse<>(true, enrollment, "enrolled successfully", HttpStatus.OK.value(), LocalDateTime.now()));
}
catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(new ApiResponse<>(false, null, "Failed to enroll student : " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value(),LocalDateTime.now()));
}
}
@GetMapping
public ResponseEntity<ApiResponse<List<Enrollment>>> getAllEnrollmentss() {
try {
List<Enrollment> enrollments = enrollmentService.getAllEnrollments();
return ResponseEntity.status(HttpStatus.CREATED)
.body(new ApiResponse<>(true, enrollments, "Enrollments listed succesfully", HttpStatus.CREATED.value(), LocalDateTime.now()));
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(new ApiResponse<>(false, null, "Failed to list enrollments: " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value(), LocalDateTime.now()));
}
}
@GetMapping("/api/students/{studentId}/enrollments")
public ResponseEntity<ApiResponse<Optional<Enrollment>>> getEnrollmentForStudent(@PathVariable Long studentId) {
try {
Optional<Enrollment> enrollment = enrollmentService.getEnrollmentForStudent(studentId);
return ResponseEntity.status(HttpStatus.CREATED)
.body(new ApiResponse<>(true, enrollment, "student enrollment is get succesfully", HttpStatus.CREATED.value(), LocalDateTime.now()));
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(new ApiResponse<>(false, null, "Failed " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value(), LocalDateTime.now()));
}
}
@GetMapping("api/courses/{courseId}/enrollments")
public ResponseEntity<ApiResponse<Optional<Enrollment>>> getEnrollmentForCourse(@PathVariable Long courseId) {
try {
Optional<Enrollment> enrollment = enrollmentService.getEnrollmentForCourse(courseId);
return ResponseEntity.status(HttpStatus.CREATED)
.body(new ApiResponse<>(true, enrollment, "student enrollment is get succesfully", HttpStatus.CREATED.value(), LocalDateTime.now()));
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(new ApiResponse<>(false, null, "Failed " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value(), LocalDateTime.now()));
}
}
@PutMapping("/{id}")
public ResponseEntity<ApiResponse<Enrollment>> updateEnrollment(@PathVariable Long id, @Valid @RequestBody UpdateEnrollmentDTO enrollmenToBeUpdated){
try {
Enrollment enrollment = enrollmentService.updateEnrollment(id, enrollmenToBeUpdated);
if (enrollment != null) {
return ResponseEntity.ok(new ApiResponse<>(true, enrollment, "Enrollment updated successfully", HttpStatus.OK.value(),LocalDateTime.now()));
} else {
return ResponseEntity.status(HttpStatus.NOT_FOUND)
.body(new ApiResponse<>(false, null, "Enrollment not found", HttpStatus.NOT_FOUND.value(),LocalDateTime.now()));
}
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(new ApiResponse<>(false, null, "Failed to update enrollment " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value(),LocalDateTime.now()));
}
}
@DeleteMapping("api/enrollments/{id}")
public ResponseEntity<ApiResponse<Void>> deleteEnrollment(@PathVariable Long id) {
try {
enrollmentService.deleteEnrollment(id);
return ResponseEntity.ok(new ApiResponse<>(true, null, "Enrollment deleted successfully", HttpStatus.OK.value(),LocalDateTime.now()));
} catch (Exception e) {
return ResponseEntity.status(HttpStatus.INTERNAL_SERVER_ERROR)
.body(new ApiResponse<>(false, null, "Failed to delete enrollment: " + e.getMessage(), HttpStatus.INTERNAL_SERVER_ERROR.value(),LocalDateTime.now()));
}
}
}
Task: Create an Advanced Student Management System Using Spring Boot, MySQL Database, and REST APIs
Objective:
Your task is to create an advanced Student Management System using Spring Boot, MySQL, and RESTful APIs. This system will manage not only students but also courses and enrollments. You will create a relational database structure that includes multiple entities and relationships between them. This exercise will help you understand how to build a more complex CRUD application with multiple entities and relationships using Spring Boot, JPA, and MySQL.
user this discussion for help:
https://github.com/dgPadBootcamps/Java-Bootcamp-2024/discussions/195
Make Sure to use the best practice architecture discussed in the latest sessions
Requirements:
student_management
.application.properties
(orapplication.yml
) file, configure the connection to the MySQL database, including the database URL, username, and password.Entity Classes:
a. Student:
id
: Primary key, auto-generated.firstName
: String, not null.lastName
: String, not null.email
: String, not null, unique.age
: Integer.enrollments
: One-to-Many relationship with theEnrollment
entity.b. Course:
id
: Primary key, auto-generated.courseName
: String, not null.courseCode
: String, not null, unique.credits
: Integer.instructor
: String, not null.enrollments
: One-to-Many relationship with theEnrollment
entity.c. Enrollment:
id
: Primary key, auto-generated.student
: Many-to-One relationship with theStudent
entity.course
: Many-to-One relationship with theCourse
entity.enrollmentDate
: Date of enrollment.grade
: String, grade received in the course.@OneToMany
,@ManyToOne
, and@JoinColumn
.StudentRepository
,CourseRepository
, andEnrollmentRepository
should extendJpaRepository
.StudentService
,CourseService
, andEnrollmentService
.Controller Layer:
a. Student Endpoints:
POST /api/students
GET /api/students
GET /api/students/{id}
id
(the student's ID).PUT /api/students/{id}
id
(the student's ID).DELETE /api/students/{id}
id
(the student's ID).b. Course Endpoints:
POST /api/courses
GET /api/courses
GET /api/courses/{id}
id
(the course's ID).PUT /api/courses/{id}
id
(the course's ID).DELETE /api/courses/{id}
id
(the course's ID).c. Enrollment Endpoints:
POST /api/enrollments
studentId
,courseId
,enrollmentDate
, andgrade
.GET /api/enrollments
GET /api/students/{studentId}/enrollments
studentId
.GET /api/courses/{courseId}/enrollments
courseId
.PUT /api/enrollments/{id}
id
(the enrollment's ID).DELETE /api/enrollments/{id}
id
(the enrollment's ID).email
field in theStudent
entity is unique and follows a valid email format.courseCode
field in theCourse
entity is unique.grade
field in theEnrollment
entity follows a specific format (e.g.,A
,B
,C
, etc.).Student
,Course
, andEnrollment
) are correctly handled in both the database and the application.The task is submitted using Postman collection and code snippets as usual in addition to screenshots from the database