web/JPA

JPA 관계 유형별 엔티티 설정 방법

반응형

JPA에서 관계 유형별로 엔티티를 설정하는 방법을 정리해보자.



1. 다대일 (단방향)

-> 다쪽에 @ManyToOne 으로 설정


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
@Entity
@Table(name = "student")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
 
  @Id
  @Column(name = "STUDENT_ID")
  private String id;
 
  @Column(name = "name")
  private String name;
 
  @ManyToOne
  @JoinColumn(name = "CLASSES_ID")
  private Classes classes;
 
  public void setClasses(Classes classes) {
    // 먼저 지워준다.
    classes.getStudents().remove(this);
 
    // 그리고 반을 바꾸고 학생추가
    this.classes = classes;
    classes.getStudents().add(this);
  }
 
}
cs


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
@Table(name = "classes")
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Classes {
 
  @Id
  @Column(name = "CLASSES_ID")
  private String id;
 
  @Column(name = "name")
  private String name;
}
 
cs


2. 다대일 양방향

-> 다쪽에 @ManyToOne, 일쪽에 @OneToMany 지정해서 사용

-> 다쪽인 Student에서 외래키를 가지고 있으므로 직접 조작할 있고 반대쪽은 조회만 가능

-> 이전시간에 정리한거 처럼 setClasses(), addStudent()등에 메서드에 빈곳이 없도록 해야한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
@Entity
@Table(name = "student")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
 
  @Id
  @Column(name = "STUDENT_ID")
  private String id;
 
  @Column(name = "name")
  private String name;
 
  @ManyToOne
  @JoinColumn(name = "CLASSES_ID")
  private Classes classes;
 
  public void setClasses(Classes classes) {
    // 먼저 지워준다.
    classes.getStudents().remove(this);
 
    // 그리고 반을 바꾸고 학생추가
    this.classes = classes;
    classes.getStudents().add(this);
  }
 
}
 
@Table(name = "classes")
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Classes {
 
  @Id
  @Column(name = "CLASSES_ID")
  private String id;
 
  @Column(name = "name")
  private String name;
 
  @OneToMany(mappedBy = "classes")
  private List<Student> students;
 
}
cs


3. 일대다 (단방향)

-> 일대다에서 외래키가 다쪽에 존재

-> 다대일 단방향에서 일쪽에 @JoinColumn(name = "CLASSES_ID") 추가된 형태

-> 일대다보다 있으면 다대일을 사용하자.

1
2
3
4
@JoinColumn(name = "CLASSES_ID")
@OneToMany(mappedBy = "classes")
private List<Student> students;
 
cs


4. 일대다 (양방향)

-> 일대다 매핑은 존재하지 않고 다대일 양방향으로 사용해야한다.



5. 일대일

-> 양쪽이 서로 하나의 관계만 가지는 .

-> 양쪽 테이블 모두 외래키를 가질 있다.

-> @OneToOne으로 매핑하고 주인이 엔티티에 @JoinColumn 사용하고, 나머지 엔티티에는  mappedBy 옵션을 사용한다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
@Entity
@Table(name = "student")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
 
  @Id
  @Column(name = "STUDENT_ID")
  private String id;
 
  @Column(name = "name")
  private String name;
 
  @ManyToOne
  @JoinColumn(name = "CLASSES_ID")
  private Classes classes;
 
  @OneToOne
  @JoinColumn(name = "LOCKER_ID")
  private Locker locker;
 
  public void setClasses(Classes classes) {
    // 먼저 지워준다.
    classes.getStudents().remove(this);
 
    // 그리고 반을 바꾸고 학생추가
    this.classes = classes;
    classes.getStudents().add(this);
  }
 
}
 
@Table(name = "classes")
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Locker {
 
  @Id
  @Column(name = "LOCKER_ID")
  private String id;
 
  @Column(name = "location")
  private String location;
 
  @OneToOne(mappedBy = "locker")
  private Student student;
}
cs


6. 다대다

-> 데이터베이스에서 사용하지 않는 다대다를 사용하지 말고 중간에 중점을 두어 다대일로 구별하여 처리한다.

-> 예를 들어 학생과 책의 다대다 관계를 지칭한다 했을 중간에서 학생과 책의 관계를 담당하는 엔티티 StudentBook 있다고 가정해보자.

-> Student에는 관계 테이블에서 사용될 키가 보함된   @OneToMany(mappedBy = "student") 설정한다.

-> 관계 엔티티 에는 키를 관리하는 별도의 객체를 만들어서 @IdClass(StudentBookId.class) 설정해준다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
@Entity
@Table(name = "student")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Student {
 
  @Id
  @Column(name = "STUDENT_ID")
  private String id;
 
  @Column(name = "name")
  private String name;
 
  // 다대일
  @ManyToOne
  @JoinColumn(name = "CLASSES_ID")
  private Classes classes;
 
  // 일대일
  @OneToOne
  @JoinColumn(name = "LOCKER_ID")
  private Locker locker;
 
  // 다대다(중간에 관계테이블 있는경우)
  @OneToMany(mappedBy = "student")
  private List<Book> books;
 
  public void setClasses(Classes classes) {
    // 먼저 지워준다.
    classes.getStudents().remove(this);
 
    // 그리고 반을 바꾸고 학생추가
    this.classes = classes;
    classes.getStudents().add(this);
  }
 
}
 
 
@Entity
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Book {
 
  @Id
  @Column(name = "PRODUCT_ID")
  private String id;
 
  private String name;
 
}
 
@Entity
@IdClass(StudentBookId.class)
public class StudentBook {
 
  @Id
  @ManyToOne
  @JoinColumn(name = "STUDENT_ID")
  private Student student;
 
  @Id
  @ManyToOne
  @JoinColumn(name = "BOOK_ID")
  private Book book;
 
}
 
@EqualsAndHashCode
public class StudentBookId implements Serializable {
 
  private String student;
  private String book;
 
}
 
cs


반응형