Spring Boot Many-to-One Mapping

Many-to-Many relationships occur when multiple entities relate to multiple entities. Example:

  • Students can enroll in multiple Courses
  • Courses can have multiple Students


Define Student and Course Entities

We'll create a bidirectional Many-to-Many relationship between Student and Course


Student.java
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import jakarta.persistence.*;
import java.util.HashSet;
import java.util.Set;

@Entity
public class Student {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String name;

@ManyToMany(cascade = {CascadeType.PERSIST, CascadeType.MERGE})
@JoinTable(
name = "student_course",
joinColumns = @JoinColumn(name = "student_id"),
inverseJoinColumns = @JoinColumn(name = "course_id")
)
@JsonIgnoreProperties("students") // ✅ Prevents infinite loop
private Set<Course> courses = new HashSet<>();

// Getters and Setters

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getName() {
return name;
}

public void setName(String name) {
this.name = name;
}

public Set<Course> getCourses() {
return courses;
}

public void setCourses(Set<Course> courses) {
this.courses = courses;
}
}

This creates a join tablestudent_course to link students and courses.

Course.java
import com.fasterxml.jackson.annotation.JsonIgnoreProperties;
import jakarta.persistence.*;
import java.util.HashSet;
import java.util.Set;

@Entity
public class Course {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;

private String title;

@ManyToMany(mappedBy = "courses") // No @JoinTable here (already in Student)
@JsonIgnoreProperties("courses") // ✅ Prevents infinite loop
private Set<Student> students = new HashSet<>();

// Getters and Setters

public Long getId() {
return id;
}

public void setId(Long id) {
this.id = id;
}

public String getTitle() {
return title;
}

public void setTitle(String title) {
this.title = title;
}

public Set<Student> getStudents() {
return students;
}

public void setStudents(Set<Student> students) {
this.students = students;
}
}

Bidirectional Mapping: The relationship is mapped from Student to Course.

Table name : student

id name

Table name : course

id name

Table name : student_course

student_id course_id

Create JPA Repositories

StudentRepository.java
import org.springframework.data.jpa.repository.JpaRepository;

public interface StudentRepository extends JpaRepository<Student, Long> {
}
CourseRepository.java
import org.springframework.data.jpa.repository.JpaRepository;

public interface CourseRepository extends JpaRepository<Course, Long> {
}

Create Services

StudentService.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class StudentService {
@Autowired
private StudentRepository studentRepository;
@Autowired
private CourseRepository courseRepository;

// ✅ Create Student & Courses
public Student createStudentWithCourse(Student student) {
Set<Course> savedCourses = student.getCourses().stream()
.map(course -> courseRepository.save(course))
.collect(Collectors.toSet());
student.setCourses(savedCourses);
return studentRepository.save(student);
}

// ✅ Create Student & Assign Courses
public Student createStudent(StudentDTO studentDTO) {
Student student = new Student();
student.setName(studentDTO.getName());

Set<Course> courses = studentDTO.getCourseIds().stream()
.map(courseRepository::findById)
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toSet());

student.setCourses(courses);
return studentRepository.save(student);
}

// ✅ Create Student Only
public Student createStudentOnly(Student student) {
return studentRepository.save(student);
}

// ✅ Get Student by ID
public Student getStudent(Long id) {
return studentRepository.findById(id).orElseThrow(() -> new RuntimeException("Student Not Found"));
}

// ✅ Add Courses to an Existing Student
public Student addCoursesToStudent(Long studentId, Set<Long> courseIds) {
Student student = studentRepository.findById(studentId).orElseThrow(() -> new RuntimeException("Student Not Found"));

Set<Course> courses = courseIds.stream()
.map(courseRepository::findById)
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toSet());

student.getCourses().addAll(courses);
return studentRepository.save(student);
}

// ✅ Delete Student
public String deleteStudent(Long studentId) {
studentRepository.deleteById(studentId);
return "Deleted Successfully";
}
}

Create Controllers

StudentController.java
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.*;
import java.util.Set;

@RestController
@RequestMapping("/students")
public class StudentController {
@Autowired
private StudentService studentService;


// ✅ Create Student with Courses
@PostMapping
public ResponseEntity<Student> createStudentWithCourse(@RequestBody Student student) {
return ResponseEntity.ok(studentService.createStudentWithCourse(student));
}

// ✅ Create Student with Courses
@PostMapping("/createStudent")
public ResponseEntity<Student> createStudent(@RequestBody StudentDTO studentDTO) {
return ResponseEntity.ok(studentService.createStudent(studentDTO));
}

// ✅ Create Student with Courses
@PostMapping("/createStudentOnly")
public ResponseEntity<Student> createStudentOnly(@RequestBody Student student) {
return ResponseEntity.ok(studentService.createStudentOnly(student));
}

// ✅ Get Student with Courses
@GetMapping("/{id}")
public ResponseEntity<Student> getStudent(@PathVariable Long id) {
return ResponseEntity.ok(studentService.getStudent(id));
}

// ✅ Add Courses to Existing Student
@PutMapping("/{id}/courses")
public ResponseEntity<Student> addCourses(@PathVariable Long id, @RequestBody Set<Long> courseIds) {
return ResponseEntity.ok(studentService.addCoursesToStudent(id, courseIds));
}

// ✅ Add Courses to Existing Student
@DeleteMapping("/{id}")
public ResponseEntity<String> deleteCourses(@PathVariable Long id) {
return ResponseEntity.ok(studentService.deleteStudent(id));
}
}

Testing the REST API with Postman:

Once the application is running, test the endpoints:


Create Students with Courses POST:http://localhost:8080/students

Create a Student with Existing Courses POST:http://localhost:8080/students/createStudent

Get Student with Courses GET:http://localhost:8080/students/{studentID}

Create Student Only POST:http://localhost:8080/students/createStudentOnly

Add More Courses to Student PUT:http://localhost:8080/students/{studentID}/courses

Delete Courses with Student DELETE:http://localhost:8080/students/{studentID}


Whereisstuff is simple learing platform for beginer to advance level to improve there skills in technologies.we will provide all material free of cost.you can write a code in runkit workspace and we provide some extrac features also, you agree to have read and accepted our terms of use, cookie and privacy policy.
© Copyright 2024 www.whereisstuff.com. All rights reserved. Developed by whereisstuff Tech.