Reference. 한 번에 끝내는 Java/Spring 웹 개발 마스터 초격차 패키지 Online
이전 글
1. N:1
@OneToMany
에서 참조하는 값은 One에 해당하는 PK값을 Many쪽에서 FK로 가짐
→UserHistory
테이블에서는User
에 Id값을 가짐
- 일반적인 상황에서는
@ManyToOne
이 깔끔하게 엔티티를 구성
→ 해당 엔티티가 필요로 하는 FK 엔티티가 함께 가지고 있기 때문
UserHistory.java
@Entity
...
public class UserHistory extends BaseEntity{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String email;
@ManyToOne
private User user;
}
User.java
@ToString.Exclude
를 선언하지 않으면 결과 확인 순환참조로 에러 발생
@Entity
...
public class User extends BaseEntity{
...
@OneToMany(fetch = FetchType.EAGER)
@JoinColumn(name = "user_Id", insertable = false, updatable = false)
@ToString.Exclude
private List<UserHistory> userHistories = new ArrayList<>();
}
UserEntityListener.java
public class UserEntityListener {
@PostPersist
@PostUpdate
public void postPersistAndPostUpdate(Object o){
UserHistoryRepository userHistoryRepository = BeanUtils.getBean(UserHistoryRepository.class);
User user = (User) o;
UserHistory userHistory = new UserHistory();
userHistory.setName(user.getName());
userHistory.setEmail(user.getEmail());
userHistory.setUser(user);
userHistoryRepository.save(userHistory);
}
}
실행결과
@Test
void userRelationTest(){
...
System.out.println("userHistory getUser() : " + userHistoryRepository.findAll().get(0).getUser());
}
//콘솔 값
userHistory getUser() : User(super=BaseEntity(createdAt=2021-07-28T21:16:57.792881, updatedAt=2021-07-28T21:16:58.014881), id=6, name=Kim, email=kim@gmail.com, gender=MALE)
- JPA는 연관된 객체를 FK로 조회하는 것이 아니라 getter를 통해 가져오게 됌
@OneToMany
,@ManyToOne
,양방향
중 선택은 어느 엔티티에 연관 엔티티가 필요한지 알아야함UserHistory
에 값을 조회해서 보면서User
를 조회할 일은 거의 없음
User
에서 변경이력을 보기 위해서UserHistory
를 조회할 일은 많음
User
에서@OneToMany
를 활용해서UserHistory
에 연관관계를 맺는 것이 나은 방법
2. ERD → Entity 옮기기
<ERD>
<Entity>
book.java
...
public class Book extends BaseEntity{
...
@OneToOne(mappedBy = "book")
@ToString.Exclude
private BookReviewInfo bookReviewInfo;
@OneToMany
@JoinColumn(name="book_id")
@ToString.Exclude
private List<Review> reviews = new ArrayList<>();
@ManyToOne
@ToString.Exclude
private Publisher publisher;
}
BookReviewInfo.java
...
public class BookReviewInfo extends BaseEntity{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToOne(optional = false)
private Book book;
private float averageReviewScore;
private int reviewCount;
}
Publisher.java
...
public class Publisher extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
@OneToMany
@JoinColumn(name = "publisher_id")
private List<Book> books = new ArrayList<>();
}
Review.java
...
public class Review extends BaseEntity{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String title;
private String content;
private float score;
@ManyToOne
private User user;
@ManyToOne
private Book book;
}
User.java
...
public class User extends BaseEntity{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@NonNull
private String name;
@NonNull
private String email;
@Enumerated
private Gender gender;
@OneToMany(fetch = FetchType.EAGER)
@JoinColumn(name = "user_Id", insertable = false, updatable = false)
@ToString.Exclude
private List<UserHistory> userHistories = new ArrayList<>();
@OneToMany
@JoinColumn(name = "user_id")
@ToString.Exclude
private List<Review> reviews = new ArrayList<>();
}
UserHistory.java
public class UserHistory extends BaseEntity{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private String email;
@ManyToOne
private User user;
}
3. 정리
- 예제에선
@OneToMany
,@ManyToOne
모두 적용, 둘 중에 하나만 선택해도 되는 듯?
→ 실습 및 공부를 통해서 확인이 필요한 부분 @OneToMany
- 실제 데이터베이스에서는 컬럼으로 존재하지 않음 (
book_id
)
@JoinColumn
: 연관된 엔티티의 FK를 지정 (안하면 N:N 테이블 생성)
- 실제 데이터베이스에서는 컬럼으로 존재하지 않음 (
public class Publisher extends BaseEntity { ... @OneToMany @JoinColumn(name = "publisher_id") private List<Book> books = new ArrayList<>(); }
@ManyToOne
- 실제 데이터베이스에서 FK로 존재 (
book_id
,user_id
)
- 실제 데이터베이스에서 FK로 존재 (
public class Review extends BaseEntity{ ... @ManyToOne private User user; @ManyToOne private Book book; }
'백엔드 > JPA' 카테고리의 다른 글
[ JPA ] 6-1. 영속성 컨텍스트(Persistence Context) (0) | 2021.08.07 |
---|---|
[ JPA ] 5-5. Entity Relations ( N:N @ManyToMany ) (0) | 2021.08.01 |
[ JPA ] 5-3. Entity Relations ( 1:N @OneToMany ) (0) | 2021.07.25 |
[ JPA ] 5-2. Entity Relations ( 1:1 @OneToOne ) (0) | 2021.07.25 |
[ JPA ] 5-1. Entity Relations (ERD, 데이터베이스 기준 연관 관계) (0) | 2021.07.25 |