[TIL] 4주차 주특기 숙련ㅣSpring 시험
주특기 숙련 Spring 시험
오늘은 JPA 연관관계를 매핑하는 문제가 출제되었다.
문제는 총 4문제, 시간은 4시간.
순서대로 N:1 단방향, N:1 양방향, 1:N 단방향, N:M을 다대다 사용하지 않고 구현하기가 나왔다.
1) 다대일 단방향 연관관계(N:1)
여러 책(Book)들이 하나의 서점(BookStore)에 속할 수 있으므로, 다대일 관계를 적용한다.
다대일 관계에서는 '다'에 외래키가 있어야 한다.
따라서 Book 객체에서 BookStore 객체를 필드로 만들어 참조하도록 만든다.
@JoinColumn : 조인 컬럼은 외래 키를 매핑할 때 사용한다. name 속성에는 매핑할 외래 키 이름을 지정한다. 이 어노테이션은 생략할 수 있다.
// /com/exmple/spring_week_2_test/entity/Book
@Entity
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "book_store_id", nullable = false)
private BookStore bookStore;
@Column(nullable = false)
private String author;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private int price;
@Column(nullable = false)
private long quantity;
}
// /com/exmple/spring_week_2_test/entity/BookStore
@Entity
public class BookStore {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String location;
@Column(nullable = false)
private String name;
}
📚 참고자료
@ManyToOne을 사용할 때 @JoinColumn 생략
💡 summary JPA를 학습하면서 @ManyToOne 어노테이션을 통해 다대일 연관관계를 매핑할 때 @JoinColumn을 항시 같이 사용했다.
hyeon9mak.github.io
2) 다대일 양방향 연관관계(N:1)
Book : BookStore → 다대일
BookStore : Book → 일대다
이렇게 단방향 관계를 양쪽에 설정하면 양방향이다.
서점(BookStore) 객체에서 List<Book>을 필드로 가지면 된다.
// /com/exmple/spring_week_2_test/entity/Book
@Entity
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "book_store_id", nullable = false)
private BookStore bookStore;
@Column(nullable = false)
private String author;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private int price;
@Column(nullable = false)
private long quantity;
}
// /com/exmple/spring_week_2_test/entity/BookStore
@Entity
public class BookStore {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany(mappedBy = "book_store", cascade = CascadeType.REMOVE)
private List<Book> books = new ArrayList<>();
@Column(nullable = false)
private String location;
@Column(nullable = false)
private String name;
}
📚 참고자료
JPA 다대일 단방향 양방향
JPA에서 가장 많이 사용하는 관계가 N:1 이다. 다대일 엔티티 관계를 2개의 객체를 통해 예시 코드를 정리했다. 다대일 단방향 관계 시나리오 Member 객체와 Team 객체가 있다. 멤버는 팀에 속할 수 있
gdlovehush.tistory.com
3) 일대다 단방향 연관관계(1:N)
하나의 서점(BookStore)에 여러 회원(Member)이 속할 수 있으므로, 일대다 관계를 적용한다.
일대다 단방향에서는 JoinColumn 어노테이션을 명시해주어야 중간 테이블이 자동 생성되는 걸 방지할 수 있다.
// /com/exmple/spring_week_2_test/entity/BookStore
@Entity
public class BookStore {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany(cascade = CascadeType.ALL)
@JoinColumn(name = "book_store_id")
private List<Member> members = new ArrayList<>();
@OneToMany(mappedBy = "book_store", cascade = CascadeType.REMOVE)
private List<Book> books = new ArrayList<>();
@Column(nullable = false)
private String location;
@Column(nullable = false)
private String name;
}
// /com/exmple/spring_week_2_test/entity/Member
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@Column(nullable = false)
private String address;
@Column(nullable = false)
private String email;
@Column(nullable = false)
private String nickname;
@Column(nullable = false)
private String password;
@Column(nullable = false)
private String phoneNumber;
}
📚 참고자료
JPA - One To Many 단방향의 문제점
주변에서 One To Many 단방향에 관해서 물어볼 때마다 저는 항상 이렇게 대답했습니다. 김영한 님의 인프런 강의에서 봤는데~ One To Many 단방향은 좋지 않다. 차라리 양방향을 해라. 이유는 ~ 때문이
dublin-java.tistory.com
4) 다대다 양방향(N:M)
실무에서 다대다 연관관계는 사용하지 않는다고 한다.
관계형 데이터베이스는 정규화된 테이블 2개로 다대다 관계를 표현할 수 없기 때문에
중간 테이블을 만들어버린다.
그렇다면 중간 테이블을 직접 만들어보자.
회원(Member)과 책(Book)을 연결시켜줄 구매(Purchase) 객체에 각각 다대일 양방향 연관관계를 설정해준다.
// /com/exmple/spring_week_2_test/entity/Member
@Entity
public class Member {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany(mappedBy = "member")
private List<Purchase> purchases = new ArrayList<>();
@Column(nullable = false)
private String address;
@Column(nullable = false)
private String email;
@Column(nullable = false)
private String nickname;
@Column(nullable = false)
private String password;
@Column(nullable = false)
private String phoneNumber;
}
// /com/exmple/spring_week_2_test/entity/Book
@Entity
public class Book {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@OneToMany(mappedBy = "book")
private List<Purchase> members = new ArrayList<>();
@ManyToOne
@JoinColumn(name = "book_store_id", nullable = false)
private BookStore bookStore;
@Column(nullable = false)
private String author;
@Column(nullable = false)
private String name;
@Column(nullable = false)
private int price;
@Column(nullable = false)
private long quantity;
}
// /com/exmple/spring_week_2_test/entity/Purchase
@Entity
public class Purchase {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
@ManyToOne
@JoinColumn(name = "member_id")
private Member member;
@ManyToOne
@JoinColumn(name = "book_id")
private Book book;
}
📚 참고자료
[JPA] @ManyToMany, 다대다[N:M] 관계
다대다[N:M]실무에선 사용하지 않는 것을 추천한다. 사용하면 안되는 이유를 학습하자.관계형 데이터베이스는 정규화된 테이블 2개로 다대다 관계를 표현할 수 없다.연결 테이블(조인 테이블)을
ict-nroo.tistory.com
5) 완성된 엔티티 관계도
오늘의 나는
시험도 봤고, 과제 제출도 했으니 이번 숙련 주차도 잘 마무리되었다😎
이번 주차에서 가장 어려웠던 부분은 역시 JPA 였는데,
테이블 관점의 데이터베이스와 객체 관점의 JPA를 비교하면서 보는 게 너무 헷갈렸다.
객체 자체를 통째로 참조한다는 개념도 잘 그려지지 않았고..
그렇지만 확실히 간단한 어노테이션 설정만으로 객체가 매핑되는 ORM이 매우 신선했고, 편리함을 느꼈다.
이번 주차 과제를 하면서 가장 재밌었던 부분은 역시 예외처리!
기술 매니저님께 내 코드를 보여드리고, 이런 방식의 예외처리는 어떤지 여쭤봤다.
이렇게 전역에서 하는 에러 처리는 한 곳에서 에러코드를 관리할 수 있어 편리하다고 한다.
관련된 조언도 해주셨는데,
성공 메시지와 에러 메시지를 통일하는 걸 고민해보면 좋을 것 같다고 말씀해주셨다.
그 외 추천해주신 키워드!
- Spring Data JPA
- 연관관계 매핑
- 즉시 로딩, 지연 로딩
- 영속성 전이
후.. 다음 심화 주차도 힘 내보자!