앞서 실습시간에 만들었던 예제를 바탕으로 이번에는 연관관계 매핑을 할 예정이다.
현재 테이블에서는 다대다 관계는 없고 일대 다 관계만 존재한다.
STUDENT와 ENROLL의 경우 1 대 다의 관계를 가지고 SUBJECT와 ENROLL 또한 1 대 다의 관계를 가진다. 이를 참고하여 새롭게 객체스럽게 JPA를 설계해보고자 한다.
테이블 설계
앞서 설계한 ENROLL CLASS만 수정하면 된다. 기존 코드를 살펴보고 이를 수정해보자
1. 수정 전
package jpaenroll.domain;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import java.time.LocalDateTime;
@Entity
public class Enroll {
@Id @GeneratedValue
@Column(name="enrollment_id")
private Long id;
@Column(name="student_id")
private Long studentid;
@Column(name="subject_id")
private Long subjectid;
private LocalDateTime enrolldate;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Long getStudentid() {
return studentid;
}
public void setStudentid(Long studentid) {
this.studentid = studentid;
}
public Long getSubjectid() {
return subjectid;
}
public void setSubjectid(Long subjectid) {
this.subjectid = subjectid;
}
public LocalDateTime getEnrolldate() {
return enrolldate;
}
public void setEnrolldate(LocalDateTime enrolldate) {
this.enrolldate = enrolldate;
}
}
이 경우 FK를 직접 매핑한 케이스다. 이 때 수동으로 전부 연결시킬 수 있지만 이는 객체를 활용하는 방향과는 벗어난다. 또한, studentid, subject_id가 null 값이 들어가는 경우도 빈번하다. 그래서 이를 아래와 같이 수정했다.
2. 수정 후
package jpaenroll.domain;
import javax.persistence.*;
import java.time.LocalDateTime;
@Entity
public class Enroll {
@Id @GeneratedValue
@Column(name="enrollment_id")
private Long id;
@ManyToOne
@JoinColumn(name="student_id")
private Student student;
@ManyToOne
@JoinColumn(name="subject_id")
private Subject subject;
private LocalDateTime enrolldate;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public Student getStudent() {
return student;
}
public void setStudent(Student student) {
this.student = student;
}
public Subject getSubject() {
return subject;
}
public void setSubject(Subject subject) {
this.subject = subject;
}
public LocalDateTime getEnrolldate() {
return enrolldate;
}
public void setEnrolldate(LocalDateTime enrolldate) {
this.enrolldate = enrolldate;
}
}
3. JOIN
Q. 첫 번째로 수강신청에 성공한 과목의 이름은?
앞 시간에 만들었던 JpaMain의 try문을 수정해주자.
try {
// 첫 번째로 수강신청한 과목의 이름은 무엇인가?
Enroll enroll=em.find(Enroll.class, 1L);
System.out.println(enroll.getSubject().getName());
tx.commit();
}
성공적으로 과목명을 조회했다. 앞서 사용했던 방식보다 훨씬 간단하고, 이러한 형태가 객체를 타고 타는 형태이므로 객체 지향에 더 가깝다고 볼 수 있다.
조회는 정말 쉽게 끝났고 그 다음으로는 테이블 삽입 문제이다.
Q. 학번이 160165, 5학년, 전공이 수학인 학생이 JPA_BASIC 수업을 수강신청 했다. 이 때 student, enroll table에 추가하시오.
try {
// student id가 160165이고 4학, 전공이 수학인 사람을 추가하고
// 이 사람이 JPA_BASIC 과목을 추가한다한다면?
Student student = new Student();
student.setId(160165L);
student.setGrade(5);
student.setMajor(KindOfMajor.Math);
em.persist(student);
Enroll enroll = new Enroll();
enroll.setStudent(student);
enroll.setEnrolldate(LocalDateTime.now());
enroll.setSubject(em.find(Subject.class, 1101L));
em.persist(enroll);
tx.commit();
}
성공적으로 insert 한 것을 살펴볼 수 있다.
이번에 진행한 내용은 단방향만 다루었다. 양방향으로 더 코드를 간단하게 할 수 있지만 이는 선택사항이다. 왜냐하면 어차피 단방향으로도 모든 것을 다룰 수 있다. 그러므로 관계 매핑에서 단방향 설계를 잘하는 것이 가장 중요하다.
'SPRING' 카테고리의 다른 글
[Spring] JPA CASCADE (2) | 2022.08.31 |
---|---|
[Spring] JWT 실습 - 1 (2) | 2022.07.27 |
[JAVA] JPA 실습(Create table and PK/FK 설정) (0) | 2022.07.19 |
[JAVA] JPA 개념 및 예제 (0) | 2022.07.18 |
[Spring] JPA를 활용한 로그인 구현 (2) | 2022.07.15 |