In this post, I am going to explain how to model many to many mapping using a join table, where join table has a primary key column in it.
Requirement
a. One student can enrol to zero or more course
b. One course can be enrolled with zero or more students
Tables are modelled like below
STUDENT table
id |
first_name |
last_name |
|
|
|
|
|
|
COURSE table
id |
course_name |
|
|
|
|
STUDENT_COURSE_MAPPING table
id |
student_id |
course_id |
|
|
|
|
|
|
ddl.sql
CREATE TABLE `STUDENT` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`first_name` varchar(100) NOT NULL,
`last_name` varchar(200) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `UNIQUE_STUDENT_FIRST_NAME` (`first_name`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=latin1;
CREATE TABLE `COURSE` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`course_name` varchar(100) NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `UNIQUE_COURSE_NAME` (`course_name`)
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=latin1;
CREATE TABLE `STUDENT_COURSE_MAPPING` (
`id` int(10) unsigned NOT NULL AUTO_INCREMENT,
`student_id` int(10) unsigned NOT NULL,
`course_id` int(10) unsigned NOT NULL,
PRIMARY KEY (`id`),
UNIQUE KEY `UNIQUE_COURSE` (`student_id`, `course_id`),
KEY `STUDENT_COURSE_MAPPING_STUDENT_ID` (`student_id`),
KEY `STUDENT_COURSE_MAPPING_COURSE_ID` (`course_id`),
CONSTRAINT `RECORD_SPEC_CREATED_BY` FOREIGN KEY (`student_id`) REFERENCES `STUDENT` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION,
CONSTRAINT `RECORD_SPEC_UPDATED_BY` FOREIGN KEY (`course_id`) REFERENCES `COURSE` (`id`) ON DELETE NO ACTION ON UPDATE NO ACTION
) ENGINE=InnoDB AUTO_INCREMENT=9 DEFAULT CHARSET=latin1;
Entity classes are modelled like below.
Student.java
@Entity
@Table(name = "STUDENT")
public class Student implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
// bi-directional many-to-one association to StudentCourseMapping
@OneToMany(mappedBy = "student")
@JsonManagedReference
private List<StudentCourseMapping> studentCourseMappings;
.....
.....
}
Course.java
@Entity
@Table(name = "COURSE")
public class Course implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(name = "course_name")
private String courseName;
// bi-directional many-to-one association to StudentCourseMapping
@OneToMany(mappedBy = "course")
@JsonManagedReference
private List<StudentCourseMapping> studentCourseMappings;
.....
.....
}
StudentCourseMapping.java
@Entity
@Table(name = "STUDENT_COURSE_MAPPING")
public class StudentCourseMapping implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(name = "STUDENT_ID")
private Integer studentId;
@Column(name = "COURSE_ID")
private Integer courseId;
// bi-directional many-to-one association to Student
@ManyToOne
@JsonBackReference
@JoinColumn(name = "STUDENT_ID", insertable = false, updatable = false)
private Student student;
.....
.....
}
Follow below step-by-step procedure to build complete working application.
Step 1: Create new maven project ‘many-to-many-jointable-pk’.
Step 2: Update pom.xml with maven dependencies.
pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.sample.app</groupId>
<artifactId>many-to-many-jointable-pk</artifactId>
<version>1</version>
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
</parent>
<dependencies>
<!-- https://mvnrepository.com/artifact/org.springframework.boot/spring-boot-starter-data-jpa -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/com.h2database/h2 -->
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<!-- https://mvnrepository.com/artifact/org.hibernate/hibernate-envers -->
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-envers</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
</dependencies>
</project>
Step 3: Create application.properties file under src/main/resources folder.
application.properties
logging.level.root=WARN logging.level.org.hibernate=ERROR ## H2 specific properties spring.h2.console.enabled=true spring.h2.console.path=/h2 spring.datasource.url=jdbc:h2:file:~/db/myOrg.db;DB_CLOSE_ON_EXIT=FALSE;DB_CLOSE_DELAY=-1; spring.datasource.username=krishna spring.datasource.password=password123 spring.datasource.driverClassName=org.h2.Driver ## JPA specific properties # Creates the schema, destroying previous data. spring.jpa.hibernate.ddl-auto=create spring.jpa.database-platform=org.hibernate.dialect.H2Dialect spring.jpa.show-sql=true #spring.jpa.properties.hibernate.format_sql=true ## Database connection pooling properties # Number of ms to wait before throwing an exception if no connection is available. spring.datasource.max-wait=10000 # Maximum number of active connections that can be allocated from this pool at the same time. spring.datasource.tomcat.max-active=10 spring.datasource.tomcat.max-idle=5 spring.datasource.tomcat.min-idle=3 spring.jackson.serialization.FAIL_ON_EMPTY_BEANS=false
Step 4: Define entity classes.
Course.java
package com.sample.app.entity;
import java.io.Serializable;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import com.fasterxml.jackson.annotation.JsonManagedReference;
@Entity
@Table(name = "COURSE")
public class Course implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(name = "course_name")
private String courseName;
// bi-directional many-to-one association to StudentCourseMapping
@OneToMany(mappedBy = "course")
@JsonManagedReference
private List<StudentCourseMapping> studentCourseMappings;
public Course() {
}
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getCourseName() {
return this.courseName;
}
public void setCourseName(String courseName) {
this.courseName = courseName;
}
public List<StudentCourseMapping> getStudentCourseMappings() {
return this.studentCourseMappings;
}
public void setStudentCourseMappings(List<StudentCourseMapping> studentCourseMappings) {
this.studentCourseMappings = studentCourseMappings;
}
/*
* public StudentCourseMapping addStudentCourseMapping(StudentCourseMapping
* studentCourseMapping) { getStudentCourseMappings().add(studentCourseMapping);
* studentCourseMapping.setCourse(this);
*
* return studentCourseMapping; }
*
* public StudentCourseMapping removeStudentCourseMapping(StudentCourseMapping
* studentCourseMapping) {
* getStudentCourseMappings().remove(studentCourseMapping);
* studentCourseMapping.setCourse(null);
*
* return studentCourseMapping; }
*/
}
Student.java
package com.sample.app.entity;
import java.io.Serializable;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;
import com.fasterxml.jackson.annotation.JsonManagedReference;
@Entity
@Table(name = "STUDENT")
public class Student implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(name = "first_name")
private String firstName;
@Column(name = "last_name")
private String lastName;
// bi-directional many-to-one association to StudentCourseMapping
@OneToMany(mappedBy = "student")
@JsonManagedReference
private List<StudentCourseMapping> studentCourseMappings;
public Student() {
}
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public String getFirstName() {
return this.firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return this.lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public List<StudentCourseMapping> getStudentCourseMappings() {
return this.studentCourseMappings;
}
public void setStudentCourseMappings(List<StudentCourseMapping> studentCourseMappings) {
this.studentCourseMappings = studentCourseMappings;
}
/*public StudentCourseMapping addStudentCourseMapping(StudentCourseMapping studentCourseMapping) {
getStudentCourseMappings().add(studentCourseMapping);
studentCourseMapping.setStudent(this);
return studentCourseMapping;
}
public StudentCourseMapping removeStudentCourseMapping(StudentCourseMapping studentCourseMapping) {
getStudentCourseMappings().remove(studentCourseMapping);
studentCourseMapping.setStudent(null);
return studentCourseMapping;
}*/
}
StudentCourseMapping.java
package com.sample.app.entity;
import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;
import com.fasterxml.jackson.annotation.JsonBackReference;
@Entity
@Table(name = "STUDENT_COURSE_MAPPING")
public class StudentCourseMapping implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@Column(name = "STUDENT_ID")
private Integer studentId;
@Column(name = "COURSE_ID")
private Integer courseId;
// bi-directional many-to-one association to Student
@ManyToOne
@JsonBackReference
@JoinColumn(name = "STUDENT_ID", insertable = false, updatable = false)
private Student student;
// bi-directional many-to-one association to Course
@ManyToOne
@JsonBackReference
@JoinColumn(name = "COURSE_ID", insertable = false, updatable = false)
private Course course;
public StudentCourseMapping() {
}
public Integer getId() {
return this.id;
}
public void setId(Integer id) {
this.id = id;
}
public Student getStudent() {
return this.student;
}
public void setStudent(Student student) {
this.student = student;
}
public Course getCourse() {
return this.course;
}
public void setCourse(Course course) {
this.course = course;
}
public Integer getStudentId() {
return studentId;
}
public void setStudentId(Integer studentId) {
this.studentId = studentId;
}
public Integer getCourseId() {
return courseId;
}
public void setCourseId(Integer courseId) {
this.courseId = courseId;
}
}
Step 5: Define repository interfaces.
CourseRepository.java
package com.sample.app.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.sample.app.entity.Course;
public interface CourseRepository extends JpaRepository<Course, Integer> {
}
StudentRepository.java
package com.sample.app.repository;
import org.springframework.data.jpa.repository.JpaRepository;
import com.sample.app.entity.Student;
public interface StudentRepository extends JpaRepository<Student, Integer> {
}
StudentCourseMappingRepository.java
package com.sample.app.repository;
import java.util.List;
import org.springframework.data.repository.CrudRepository;
import org.springframework.data.repository.query.Param;
import com.sample.app.entity.StudentCourseMapping;
import org.springframework.data.jpa.repository.Query;
public interface StudentCourseMappingRepository extends CrudRepository<StudentCourseMapping, Integer> {
@Query(value = "select s.course_id from STUDENT_COURSE_MAPPING s WHERE s.student_id= :studentId", nativeQuery = true)
List<Integer> findAllCourseIds(@Param("studentId") Integer studentId);
}
Step 6: Define service layer interfaces.
CourseService.java
package com.sample.app.service;
import com.sample.app.dto.CourseRequestDto;
import com.sample.app.dto.CourseResponseDto;
public interface CourseService {
public CourseResponseDto createCourse(CourseRequestDto courseDto);
}
StudentService.java
package com.sample.app.service;
import java.util.Set;
import com.sample.app.dto.StudentAndCoursesRespDto;
import com.sample.app.dto.StudentRequestDto;
import com.sample.app.dto.StudentResponseDto;
public interface StudentService {
public StudentResponseDto createStudent(StudentRequestDto studentDto);
public void addCoursesToStudent(Integer studentId, Set<Integer> courseIds);
public StudentAndCoursesRespDto getStudentDetails(Integer studentId);
}
Step 7: Define service layer implementation classes.
CourseServiceImpl.java
package com.sample.app.service.impl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.sample.app.dto.CourseRequestDto;
import com.sample.app.dto.CourseResponseDto;
import com.sample.app.entity.Course;
import com.sample.app.repository.CourseRepository;
import com.sample.app.service.CourseService;
@Service
public class CourseServiceImpl implements CourseService {
@Autowired
private CourseRepository courseRepository;
@Override
@Transactional
public CourseResponseDto createCourse(CourseRequestDto courseDto) {
Course course = new Course();
course.setCourseName(courseDto.getCourseName());
course = courseRepository.save(course);
CourseResponseDto dto = new CourseResponseDto();
dto.setCourseName(course.getCourseName());
dto.setId(course.getId());
return dto;
}
}
StudentServiceImpl.java
package com.sample.app.service.impl;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import com.sample.app.dto.CourseResponseDto;
import com.sample.app.dto.StudentAndCoursesRespDto;
import com.sample.app.dto.StudentRequestDto;
import com.sample.app.dto.StudentResponseDto;
import com.sample.app.entity.Course;
import com.sample.app.entity.Student;
import com.sample.app.entity.StudentCourseMapping;
import com.sample.app.repository.CourseRepository;
import com.sample.app.repository.StudentCourseMappingRepository;
import com.sample.app.repository.StudentRepository;
import com.sample.app.service.StudentService;
@Service
public class StudentServiceImpl implements StudentService {
@Autowired
private StudentRepository studentRepo;
@Autowired
private StudentCourseMappingRepository studentCourseMappingRepository;
@Autowired
private CourseRepository courseRepository;
@Override
@Transactional
public StudentResponseDto createStudent(StudentRequestDto studentDto) {
Student student = new Student();
student.setFirstName(studentDto.getFirstName());
student.setLastName(studentDto.getLastName());
student = studentRepo.save(student);
StudentResponseDto dto = new StudentResponseDto();
dto.setId(student.getId());
dto.setFirstName(student.getFirstName());
dto.setLastName(student.getLastName());
return dto;
}
@Override
@Transactional
public void addCoursesToStudent(Integer studentId, Set<Integer> courseIds) {
List<StudentCourseMapping> mappings = new ArrayList<>();
for (Integer courseId : courseIds) {
StudentCourseMapping mapping = new StudentCourseMapping();
mapping.setStudentId(studentId);
mapping.setCourseId(courseId);
mappings.add(mapping);
}
studentCourseMappingRepository.saveAll(mappings);
}
@Override
public StudentAndCoursesRespDto getStudentDetails(Integer studentId) {
Student student = studentRepo.findById(studentId).get();
StudentAndCoursesRespDto respDto = new StudentAndCoursesRespDto();
respDto.setFirstName(student.getFirstName());
respDto.setLastName(student.getLastName());
respDto.setId(student.getId());
List<Integer> courseIds = studentCourseMappingRepository.findAllCourseIds(studentId);
if (courseIds == null || courseIds.isEmpty()) {
return respDto;
}
List<Course> courses = courseRepository.findAllById(courseIds);
List<CourseResponseDto> coursesDto = new ArrayList<>();
for (Course course : courses) {
CourseResponseDto courseDto = new CourseResponseDto();
courseDto.setId(course.getId());
courseDto.setCourseName(course.getCourseName());
coursesDto.add(courseDto);
}
respDto.setCourses(coursesDto);
return respDto;
}
}
Step 8: Define dto layer classes.
CourseRequestDto.java
package com.sample.app.dto;
public class CourseRequestDto {
private String courseName;
public String getCourseName() {
return courseName;
}
public void setCourseName(String courseName) {
this.courseName = courseName;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((courseName == null) ? 0 : courseName.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
CourseRequestDto other = (CourseRequestDto) obj;
if (courseName == null) {
if (other.courseName != null)
return false;
} else if (!courseName.equals(other.courseName))
return false;
return true;
}
}
CourseResponseDto.java
package com.sample.app.dto;
public class CourseResponseDto {
private int id;
private String courseName;
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
public String getCourseName() {
return courseName;
}
public void setCourseName(String courseName) {
this.courseName = courseName;
}
}
StudentAndCoursesRespDto.java
package com.sample.app.dto;
import java.util.List;
public class StudentAndCoursesRespDto extends StudentResponseDto {
private List<CourseResponseDto> courses;
public List<CourseResponseDto> getCourses() {
return courses;
}
public void setCourses(List<CourseResponseDto> courses) {
this.courses = courses;
}
}
StudentCourseMappingDto.java
package com.sample.app.dto;
import java.util.Set;
public class StudentCourseMappingDto {
private Integer studentId;
private Set<Integer> courseIds;
public Integer getStudentId() {
return studentId;
}
public void setStudentId(Integer studentId) {
this.studentId = studentId;
}
public Set<Integer> getCourseIds() {
return courseIds;
}
public void setCourseIds(Set<Integer> courseIds) {
this.courseIds = courseIds;
}
}
StudentRequestDto.java
package com.sample.app.dto;
public class StudentRequestDto {
private String firstName;
private String lastName;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((firstName == null) ? 0 : firstName.hashCode());
result = prime * result + ((lastName == null) ? 0 : lastName.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj)
return true;
if (obj == null)
return false;
if (getClass() != obj.getClass())
return false;
StudentRequestDto other = (StudentRequestDto) obj;
if (firstName == null) {
if (other.firstName != null)
return false;
} else if (!firstName.equals(other.firstName))
return false;
if (lastName == null) {
if (other.lastName != null)
return false;
} else if (!lastName.equals(other.lastName))
return false;
return true;
}
}
StudentResponseDto.java
package com.sample.app.dto;
public class StudentResponseDto {
private String firstName;
private String lastName;
private int id;
public String getFirstName() {
return firstName;
}
public void setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
return lastName;
}
public void setLastName(String lastName) {
this.lastName = lastName;
}
public int getId() {
return id;
}
public void setId(int id) {
this.id = id;
}
}
Step 8: Define swagger configuration.
SwaggerConfig.java
package com.sample.app.config;
import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
import org.springframework.context.annotation.Bean;
import org.springframework.stereotype.Component;
import springfox.documentation.builders.ApiInfoBuilder;
import springfox.documentation.builders.PathSelectors;
import springfox.documentation.builders.RequestHandlerSelectors;
import springfox.documentation.service.ApiInfo;
import springfox.documentation.spi.DocumentationType;
import springfox.documentation.spring.web.plugins.Docket;
import springfox.documentation.swagger2.annotations.EnableSwagger2;
@Component
@EnableAutoConfiguration
@EnableSwagger2
public class SwaggerConfig {
@Bean
public Docket userApi() {
return new Docket(DocumentationType.SWAGGER_2).apiInfo(apiInfo()).select().paths(PathSelectors.any())
.apis(RequestHandlerSelectors.basePackage("com.sample.app.controller")).build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder().title("Query builder").description("Query builder using spring specification")
.version("2.0").build();
}
}
Step 9: Define controller classes.
CourseController.java
package com.sample.app.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.sample.app.dto.CourseRequestDto;
import com.sample.app.dto.CourseResponseDto;
import com.sample.app.service.CourseService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@RestController
@Api(tags = "Course Controller", value = "This section contains Course specific operations")
@RequestMapping(value = "/v1/courses")
public class CourseController {
@Autowired
private CourseService courseService;
@ApiOperation(value = "Create new course", notes = "Create new course")
@PostMapping(produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<CourseResponseDto> saveCourse(@RequestBody CourseRequestDto courseDto) {
CourseResponseDto course = courseService.createCourse(courseDto);
return new ResponseEntity<>(course, HttpStatus.CREATED);
}
}
StudentController.java
package com.sample.app.controller;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import com.sample.app.dto.StudentAndCoursesRespDto;
import com.sample.app.dto.StudentCourseMappingDto;
import com.sample.app.dto.StudentRequestDto;
import com.sample.app.dto.StudentResponseDto;
import com.sample.app.service.StudentService;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
@RestController
@Api(tags = "Student Controller", value = "This section contains student specific operations")
@RequestMapping(value = "/v1/students")
public class StudentController {
@Autowired
private StudentService studentService;
@ApiOperation(value = "Add new student", notes = "Add new student")
@PostMapping(produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<StudentResponseDto> saveStudent(@RequestBody StudentRequestDto studentDto) {
StudentResponseDto student = studentService.createStudent(studentDto);
return new ResponseEntity<>(student, HttpStatus.CREATED);
}
@ApiOperation(value = "Add courses to the student", notes = "Add courses to the student")
@PostMapping(value = "/add-course", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity addCoursesToStudent(@RequestBody StudentCourseMappingDto studentCourseMappingDto) {
studentService.addCoursesToStudent(studentCourseMappingDto.getStudentId(),
studentCourseMappingDto.getCourseIds());
return new ResponseEntity<>(HttpStatus.CREATED);
}
@ApiOperation(value = "Get Student by Id", notes = "Get student by id")
@GetMapping(value = "/{id}", produces = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<StudentAndCoursesRespDto> getStudentById(@PathVariable final Integer id) {
StudentAndCoursesRespDto studentAndCoursesRespDto = studentService.getStudentDetails(id);
return new ResponseEntity<>(studentAndCoursesRespDto, HttpStatus.OK);
}
}
Step 10: Define main application class.
App.java
package com.sample.app;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class App {
public static void main(String args[]) {
SpringApplication.run(App.class, args);
}
}
Total project structure looks like below.
Run App.java.
Open the url ‘http://localhost:8080/swagger-ui.html’ in browser and play with swagger API.
You can download complete working application from below link.
https://github.com/harikrishna553/springboot/tree/master/jpa/many-to-many-jointable-pk
No comments:
Post a Comment