Notice
Recent Posts
Recent Comments
Link
«   2024/11   »
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
Archives
Today
Total
관리 메뉴

개발자되기 프로젝트

N : 1 연관관계 #2 본문

JPA

N : 1 연관관계 #2

Seung__ 2021. 6. 21. 23:30

다른 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
Comments