Spring boot JPA (2) - Relationship
0. 테이블 관계 요약
1. One-To-One Relationship
Entity
Course
@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Course {
@Id
@SequenceGenerator(
name = "course_sequence",
sequenceName = "course_sequence",
allocationSize = 1
)
@GeneratedValue(
strategy = GenerationType.SEQUENCE,
generator = "course_sequence"
)
private Long courseId;
private String title;
private Integer credit;
}
CourseMaterial
@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class CourseMaterial {
@Id
@SequenceGenerator(
name = "course_material_sequence",
sequenceName = "course_material_sequence",
allocationSize = 1
)
@GeneratedValue(
strategy = GenerationType.SEQUENCE,
generator = "course_material_sequence"
)
private Long courseMaterialId;
private String url;
@OneToOne
@JoinColumn(
name = "course_id",
referencedColumnName = "courseId"
)
private Course course;
}
(1) @OneToOne : RelationShip 지정
(2) @JoinColumn : FK 컬럼 지정 및 이름 설정
테스팅
@SpringBootTest
class CourseMaterialRepositoryTest {
@Autowired
private CourseMaterialRepository repository;
@Test
public void SaveCourseMatarial() {
Course course = Course.builder()
.title("Math")
.credit(10)
.build();
CourseMaterial courseMaterial =
CourseMaterial.builder()
.url("www.naver.com")
.course(course)
.build();
repository.save(courseMaterial);
}
}
- Course의 row가 없는 상태로 CourseMaterial은 생성 시, CourseMaterial은 courseId가 없으므로 오류 발생
2. Cascade Types
What is Cascaidng ?
- When we perform some action on the target entity, the same action will be applied to the associated entity
Entity
CourseMaterial
@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class CourseMaterial {
@Id
@SequenceGenerator(
name = "course_material_sequence",
sequenceName = "course_material_sequence",
allocationSize = 1
)
@GeneratedValue(
strategy = GenerationType.SEQUENCE,
generator = "course_material_sequence"
)
private Long courseMaterialId;
private String url;
@OneToOne(
cascade = CascadeType.ALL
)
@JoinColumn(
name = "course_id",
referencedColumnName = "courseId"
)
private Course course;
}
CascadeType.ALL
(1) Cascade Type PERSIST propagates the persist operation from a parent to a child entity.
(2) So, When we save the CourseMaterail entity, the Course entity will also get saved.
3. Fetch Types
Entity
@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
@ToString(exclude = "course")
public class CourseMaterial {
@Id
@SequenceGenerator(
name = "course_material_sequence",
sequenceName = "course_material_sequence",
allocationSize = 1
)
@GeneratedValue(
strategy = GenerationType.SEQUENCE,
generator = "course_material_sequence"
)
private Long courseMaterialId;
private String url;
@OneToOne(
cascade = CascadeType.ALL,
fetch = FetchType.LAZY
)
@JoinColumn(
name = "course_id",
referencedColumnName = "courseId"
)
private Course course;
}
(1) FetchType.LAZY : 데이터 조회 시, 선택한 Entity만 조회
(2) FetchType.EAGER : 데이터 조회 시, 연관된 모든 Enitity 조회
4. Uni & Bi directional relationship
Entity
@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Course {
@Id
@SequenceGenerator(
name = "course_sequence",
sequenceName = "course_sequence",
allocationSize = 1
)
@GeneratedValue(
strategy = GenerationType.SEQUENCE,
generator = "course_sequence"
)
private Long courseId;
private String title;
private Integer credit;
@OneToOne(
mappedBy = "course"
)
private CourseMaterial courseMaterial;
}
(1) @JoinColumn : The annotiation indicates that this entity is the owner of the relationship(FK 소유)
(2) mappedBy : mappedBy indicates that the entity in the inverse of the side relationship. this also means that we can access the other table from the class which we have annotated with "mappedBy"
=> Perform fully bidirectional relationship
5. JPA One-To-Many Relationship
Entity
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Teacher {
@Id
@SequenceGenerator(
name = "teacher_sequence",
sequenceName = "teacher_sequence",
allocationSize = 1
)
@GeneratedValue(
strategy = GenerationType.SEQUENCE,
generator = "teacher_sequence"
)
private Long teacherId;
private String firstName;
private String lastName;
@OneToMany(
cascade = CascadeType.ALL
)
@JoinColumn(
name = "teacher_id",
referencedColumnName = "teacherId"
)
private List<Course> courses;
}
테스팅
@SpringBootTest
class TeacherRepositoryTest {
@Autowired
private TeacherRepository teacherRepository;
@Test
public void saveTeacher() {
Course courseDBA = Course.builder()
.title("DBA")
.credit(11)
.build();
Course courseJAVA = Course.builder()
.title("JAVA")
.credit(4)
.build();
Teacher teacher =
Teacher.builder()
.firstName("HEEDO")
.lastName("CHE")
.courses(List.of(courseDBA, courseJAVA))
.build();
teacherRepository.save(teacher);
}
}
6. JPA Many-To-One Relationship
Entity
Course 엔티티에 ManyToOne 적용
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
@Builder
public class Teacher {
@Id
@SequenceGenerator(
name = "teacher_sequence",
sequenceName = "teacher_sequence",
allocationSize = 1
)
@GeneratedValue(
strategy = GenerationType.SEQUENCE,
generator = "teacher_sequence"
)
private Long teacherId;
private String firstName;
private String lastName;
}
@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Course {
@Id
@SequenceGenerator(
name = "course_sequence",
sequenceName = "course_sequence",
allocationSize = 1
)
@GeneratedValue(
strategy = GenerationType.SEQUENCE,
generator = "course_sequence"
)
private Long courseId;
private String title;
private Integer credit;
@OneToOne(
mappedBy = "course"
)
private CourseMaterial courseMaterial;
@ManyToOne(
cascade = CascadeType.ALL
)
@JoinColumn(
name = "teacher_id",
referencedColumnName = "teacherId"
)
private Teacher teacher;
}
테스팅
@SpringBootTest
class CourseRepository {
@Autowired
private CourseRepository courseRepository;
@Test
public void saveCourseWithTeacher() {
Teacher teacher = Teacher.builder()
.firstName("JISUB")
.lastName("LIM")
.build();
Course course = Course
.builder()
.title("Python")
.credit(8)
.teacher(teacher)
.build();
courseRepository.save(course);
}
}
7. Paging and Sorting
Entity
1) Course Pagination
테스팅
@SpringBootTest
class CourseRepository {
@Autowired
private CourseRepository courseRepository;
@Test
public void findAllPagination() {
Pageable firstPageWithThreeRecord =
PageRequest.of(0, 3);
Pageable secondPageWithTwoRecords =
PageRequest.of(1,2);
List<Course> courses =
courseRepository.findAll(firstPageWithThreeRecord).getContent();
long totalElements =
courseRepository.findAll(firstPageWithThreeRecord).getTotalElements();
long totalPages =
courseRepository.findAll(firstPageWithThreeRecord).getTotalPages();
// 전체 행 count
System.out.println("totalElements = " + totalElements);
// 전체 page count
System.out.println("totalPages = " + totalPages);
// page 행
System.out.println("courses = " + courses);
}
}
(1) Create or obtain a PageRequest object, which is an implementation of the Pageable inteface
(2) Pass the PageRequest object as an argument to the repository method we intend to use like size, sort and etc..
2) Course Pagination & Sorting
테스팅
@SpringBootTest
class CourseRepository {
@Autowired
private CourseRepository courseRepository;
@Test
public void findAllSorting() {
Pageable sortByTitle =
PageRequest.of(0, 2, Sort.by("title"));
Pageable sortByCredit =
PageRequest.of(0,2,Sort.by("credit").descending());
Pageable sortByTitleAndCreditDesc =
PageRequest.of(
0,2,Sort.by("title").descending().and(Sort.by("credit"))
);
List<Course> courses
= courseRepository.findAll(sortByTitle).getContent();
System.out.println("courses = " + courses);
}
}
3) Course Pagination & Sorting using repository
Repository
@Repository
public interface CourseRepository extends JpaRepository<Course, Long> {
Page<Course> findByTitleContaining(
String title,
Pageable pageRequest
);
}
테스팅
@SpringBootTest
class CourseRepository {
@Autowired
private CourseRepository courseRepository;
@Test
public void printFindByTitleContaining() {
Pageable firstPageTenRecords =
PageRequest.of(0,10);
List<Course> courses =
courseRepository.findByTitleContaining(
"D",
firstPageTenRecords
).getContent();
System.out.println("courses = " + courses);
}
}
8. JPA Many-To-Many Relationship
Entity
@Entity
@Data
@AllArgsConstructor
@NoArgsConstructor
@Builder
public class Course {
@Id
@SequenceGenerator(
name = "course_sequence",
sequenceName = "course_sequence",
allocationSize = 1
)
@GeneratedValue(
strategy = GenerationType.SEQUENCE,
generator = "course_sequence"
)
private Long courseId;
private String title;
private Integer credit;
@OneToOne(
mappedBy = "course"
)
private CourseMaterial courseMaterial;
@ManyToOne(
cascade = CascadeType.ALL
)
@JoinColumn(
name = "teacher_id",
referencedColumnName = "teacherId"
)
private Teacher teacher;
@ManyToMany(
cascade = CascadeType.ALL
)
@JoinTable(
name = "student_course_map",
joinColumns = @JoinColumn(
name = "course_id",
referencedColumnName = "courseId"
),
inverseJoinColumns = @JoinColumn(
name = "student_id",
referencedColumnName = "studentId"
)
)
private List<Student> students;
public void addStudents(Student student) {
if(students == null) students = new ArrayList<>();
students.add(student);
}
}
테스팅
@SpringBootTest
class CourseRepositoryTest {
@Autowired
private CourseRepository courseRepository;
@Test
public void saveCourseWithStudentAndTeacher() {
Teacher teacher = Teacher.builder()
.firstName("Lizze")
.lastName("KIM")
.build();
Student student = Student.builder()
.firstName("dodo")
.lastName("lee")
.emailId("[email protected]")
.build();
Course course = Course
.builder()
.title("AI")
.credit(2)
.teacher(teacher)
.build();
course.addStudents(student);
courseRepository.save(course);
}
}
참고
Spring Data JPA Tutorial | Full In-depth Course - Daily Code Buffer
https://www.baeldung.com/
Author And Source
이 문제에 관하여(Spring boot JPA (2) - Relationship), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@kimkevin90/Spring-boot-JPA-2-Relationship저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)