일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- JPQL
- Exception
- transaction
- 스프링
- db
- kotlin
- JDBC
- 알고리즘
- Android
- SpringBoot
- 백준
- QueryDSL
- 스프링 핵심 원리
- spring
- 김영한
- 인프런
- Servlet
- pointcut
- jpa
- Proxy
- 자바
- springdatajpa
- http
- Greedy
- Spring Boot
- AOP
- java
- 그리디
- Thymeleaf
- 스프링 핵심 기능
- Today
- Total
개발자되기 프로젝트
N : 1 연관관계 #2 본문
다른 entiry에 대해서도 연관관계를 맺어주자.
1. Book
1) Book : Review = 1 : N --> @OneToMany -->중간 table 만들지 않기 위해 @JoinColumn필수
@JoinColumn(name = "book_id") --> name = "one_PK", 현재 class의 PK를 many의 FK로.
List<Review> reviews = new ArraryList<>(); --> Null Point Exception방지를 위해 생성.
2) Book : Publisher = N : 1 --> @ManyToOne
@Entity
@NoArgsConstructor
@Data
@EntityListeners(value = AuditingEntityListener.class)
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public class Book extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String name;
private Long authorId;
private String category;
@OneToOne(mappedBy = "book")
@ToString.Exclude
private BookReviewInfo bookReviewInfo;
@OneToMany
@JoinColumn(name = "book_id") //중간 테이블 만들지 않기 위해, 나의pk를 상대의 fk로
@ToString.Exclude
private List<Review> reviews = new ArrayList<>(); //null point exception 방지
@ManyToOne
@ToString.Exclude
private Publisher publisher;
}
* Book Repository
public interface BookRepository extends JpaRepository<Book, Long> {//enum타입, id타입
}
*DDL
Book : Publisher = N : 1의 관계로 publisher의 id가 book table에 포함된 것을 알 수 있다.
many 측 table에 one의 PK가 FK로 포함된다.
Hibernate:
create table book (
id bigint generated by default as identity,
created_at timestamp,
updated_at timestamp,
author_id bigint,
category varchar(255),
name varchar(255),
publisher_id bigint,
primary key (id)
)
2. Publisher
1) Publisher : Book = 1 : N --> @OneToMany -->중간 table 만들지 않기 위해 @JoinColumn필수
@JoinColumn(name = "publisher_id") --> name = "one_PK", 현재 class의 PK를 many의 FK로.
@Entity
@NoArgsConstructor
@Data
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
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<>();
}
* Publisher Repository 생성
public interface PublisherRepository extends JpaRepository<Publisher, Long> {
}
*DDL
Hibernate:
create table publisher (
id bigint generated by default as identity,
created_at timestamp,
updated_at timestamp,
name varchar(255),
primary key (id)
)
3. Review
1) Review : Book = N : 1 --> @ManyToOne
2) Review : User = N : 1 --> @ManyToOne
@Entity
@NoArgsConstructor
@Data
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public class Review extends BaseEntity{
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
private String title;
private String content;
private float score;
//book id와 연관관계
//review 는 book 에 대해서 many to one
@ManyToOne
private Book book;
//user 연관관계
//review는 user에 대해서 many to one
@ManyToOne
private User user;
}
* Review Repository
public interface ReviewRepository extends JpaRepository<Review, Long> {
}
*DDL
1) Review : Book = N : 1 로 Book의 PK가 review table에 포함
2) Review : User = N : 1 로 User의 PK가 review table에 포함
Hibernate:
create table review (
id bigint generated by default as identity,
created_at timestamp,
updated_at timestamp,
content varchar(255),
score float not null,
title varchar(255),
book_id bigint,
user_id bigint,
primary key (id)
)
4. User
1) User : UserHistory = 1 : N --> @OneToMany -->중간 table 만들지 않기 위해 @JoinColumn필수
@JoinColumn(name = "user_id") --> name = "one_PK", 현재 class의 PK를 many의 FK로.
List<USerHistory> userHistories = new ArraryList<>(); --> Null Point Exception방지를 위해 생성.
2) User : Review = 1 : N --> @OneToMany -->중간 table 만들지 않기 위해 @JoinColumn필수
@JoinColumn(name = "user_id") --> name = "one_PK", 현재 class의 PK를 many의 FK로.
List<Review> reviews = new ArraryList<>(); --> Null Point Exception방지를 위해 생성.
@NoArgsConstructor
@AllArgsConstructor
@RequiredArgsConstructor
@Builder
@Entity //Entity에는 primary key가 꼭 필요함., JPA가 관리하고 있는 객체
@Table
@Data
@EntityListeners(value = {UserEntityListener.class})
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
public class User extends BaseEntity {
@NonNull
private String name;
@NonNull
private String email;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY) //자동으로 하나씩 증가함.
private Long id;
//이 testData는 DB에 반영하기 않고 사용하고 싶은 object data일 수 있음.
@Transient //영속성 처리에서 제외되어 db data에 반영되지 않고 해당 객체와 생명주기 같이합.
private String testData;
@Enumerated(value = EnumType.STRING)
private Gender gender;
@OneToMany(fetch = FetchType.EAGER) //이후에 자세히
@JoinColumn(name = "user_id", insertable = false, updatable = false) //엔티티가 어떤 컬럼으로 조인을 하게 될지 지정해주는 annotation
@ToString.Exclude
private List<UserHistory> userHistories = new ArrayList<>();
@OneToMany
@JoinColumn(name = "user_id")
@ToString.Exclude
private List<Review> reviews = new ArrayList<>();
}
*DDL
Hibernate:
create table user (
id bigint generated by default as identity,
created_at timestamp,
updated_at timestamp,
email varchar(255),
gender varchar(255),
name varchar(255),
primary key (id)
)
5. UserHistory
1) UserHistory : User = N : 1 --> @ManyToOne
@Entity
@NoArgsConstructor
@Data
@ToString(callSuper = true)
@EqualsAndHashCode(callSuper = true)
//@EntityListeners(value = AuditingEntityListener.class)
public class UserHistory extends BaseEntity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private long id;
//@Column(name = "user_id", insertable = false, updatable = false)
//private Long userId;
private String name;
private String email;
@ManyToOne
//@ToString.Exclude
private User user;
}
*DDL
1) UserHistory : User = N : 1 로 User의 PK가 user_history table에 포함.
Hibernate:
create table user_history (
id bigint generated by default as identity,
created_at timestamp,
updated_at timestamp,
email varchar(255),
name varchar(255),
user_id bigint,
primary key (id)
)
6. Test
JPA에서 제공하는 Relation의 장점은 각 entity의 id를 통해 불어오는 것이 아니라
간단하게 getter를 통해서 entity를 불러올 수 있다는 것이다. 깰끔하다.
@Test
@Transactional
void bookRelationTest(){
givenBookAndReview();
User user = userRepository.findByEmail("hyun@naver.com");
System.out.println("Review : " + user.getReviews());
System.out.println("Book : " + user.getReviews().get(0).getBook());
System.out.println("Publisher : " + user.getReviews().get(0).getBook().getPublisher());
//jpa의 relation의 장점은 id로 직접 불러오는게 아니라 getter로 불러울 수 있다는 것. 깰끔쓰
}
private void givenBookAndReview(){
givenReview(givenUser(), givenBook(givenPublisher()));
}
private User givenUser(){
return userRepository.findByEmail("hyun@naver.com");
}
private Book givenBook(Publisher publisher){
Book book = new Book();
book.setName("초격차");
book.setPublisher(publisher);
return bookRepository.save(book);
}
private Publisher givenPublisher(){
Publisher publisher = new Publisher();
publisher.setName("네이버");
return publisherRepository.save(publisher);
}
private void givenReview(User user, Book book){
Review review = new Review();
review.setTitle("저런..");
review.setContent("노잼....");
review.setScore(1.2f);
review.setUser(user);
review.setBook(book);
reviewRepository.save(review);
}
}
*결과 :review, book, publisher 정보를 getter를 통해 불러왔다.
'JPA' 카테고리의 다른 글
M : N(다대다) 연관관계 - 2 (0) | 2021.06.22 |
---|---|
M : N(다대다) 연관관계 - 1 (0) | 2021.06.22 |
N : 1 연관관계 - @ManyToOne (0) | 2021.06.21 |
1 : N 연관관계 - 1 (0) | 2021.06.21 |
1:1 연관관계 - 2 (0) | 2021.06.20 |