ABOUT ME

-

오늘
-
어제
-
-
  • JPA - Relation Mapping(관계 매핑)
    Back-end/JPA 2020. 6. 30. 16:52

    관계 매핑

    관계 매핑에선 항상 두 엔티티가 존재해야합니다. 주종관계를 가지고 있으며 반대쪽 레퍼런스를 가진쪽이 주인 관계가 됩니다.

    두 엔티티 클래스가 필요하기 때문에 기존 Account 클래스, 추가적으로 Study 클래스를 생성합니다.
    여기서 Study는 Account가 Study를 다수로 생성할 수 있는 개념입니다.

    @Entity
    public class Study {
    
        @Id
        @GeneratedValue
        private Long id;
    
        private String name;
    
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }

     

    Entity

    단방향

    • 관계를 정의한 쪽이 그 관계의 주인입니다.(@ManyToOne)
    • 기본값은 FK가 생성됩니다.
    • 기본값은 조인 테이블을 생성합니다.
    • @OneToMany로 매핑시 JOIN 테이블로 매핑됩니다.

    @ManyToOne

    @Entity
    public class Study {
    
        @Id
        @GeneratedValue
        private Long id;
    
        private String name;
    
        @ManyToOne
        private Account owner;
    
        public Account getOwner() {
            return owner;
        }
    
        public void setOwner(Account owner) {
            this.owner = owner;
        }
    
        public Long getId() {
            return id;
        }
    
        public void setId(Long id) {
            this.id = id;
        }
    
        public String getName() {
            return name;
        }
    
        public void setName(String name) {
            this.name = name;
        }
    }

     

    Entity

    스터디는 하나의 계정이 복수로 만들 수 있습니다. 그러므로 @ManyToOne을 사용합니다.

    @Component
    @Transactional
    public class JpaRunner implements ApplicationRunner {
    
        @PersistenceContext
        EntityManager entityManager;
    
        @Override
        public void run(ApplicationArguments args) throws Exception {
            Account account = new Account();
            account.setUsername("kimjunhyeung");
            account.setPassword("1234");
    
            Study study = new Study();
            study.setName("Spring Data JPA");
            study.setOwner(account);
    
            Session session = entityManager.unwrap(Session.class);
    
            session.save(account);
            session.save(study);
        }
    }

    Study를 Account에 추가하는 코드를 작성합니다.

    Entity

    owner라고 값을 주었지만 Account의 PK를 참고하는 owner_id라는 FK가 생성됩니다.

    @OneToMany

    @Entity
    public class Account {
    
        @Id
        @GeneratedValue
        private Long id;
    
        @Column(nullable = false, unique = true)
        private String username;
    
        private String password;
    
        @OneToMany
        private Set<Study> studies = new HashSet<>();
    }

     

    Entity

    Account는 여러개의 Study를 가질 수 있기 때문에 Set에 담아서 @OneToMany를 선언합니다.

    @Component
    @Transactional
    public class JpaRunner implements ApplicationRunner {
    
        @PersistenceContext
        EntityManager entityManager;
    
        @Override
        public void run(ApplicationArguments args) throws Exception {
            Account account = new Account();
            account.setUsername("kimjunhyeung");
            account.setPassword("1234");
    
            Study study = new Study();
            study.setName("Spring Data JPA");
    
            account.getStudies().add(study);
    
            Session session = entityManager.unwrap(Session.class);
    
            session.save(account);
            session.save(study);
        }
    }

    Set에 study를 add해줍니다.

    Entity

    2개가 아닌 3개의 테이블이 생겼는데 account_studies는 JOIN 테이블로서 각 테이블의 PK를 가지고 있게 됩니다.

    양방향

    • FK를 가지고 있는 쪽이 주인입니다. 따라서 기본값은 @ManyToOne 가지고 있는 쪽이 주인입니다.
    • 주인이 아닌쪽(@OneToMany쪽)에서 mappedBy 사용해서 관계를 맺고 있는 필드를 설정해야 합니다.

    Study 클래스

    @Entity
    public class Study {
    
        @Id @GeneratedValue
        private Long id;
    
        private String name;
    
        @ManyToOne
        private Account owner;
    
    }


    Account를 종속시킨 주인 클래스로서 @ManyToOne을 선언합니다.

    Account 클래스

    @Entity
    public class Account {
    
        @Id
        @GeneratedValue
        private Long id;
    
        @Column(nullable = false, unique = true)
        private String username;
    
        private String password;
    
        @OneToMany(mappedBy = "owner")
        private Set<Study> studies = new HashSet<>();
    }

     

    Entity

    mappedBy를 통해서 종속관계를 설정해주어야 합니다.

    @Component
    @Transactional
    public class JpaRunner implements ApplicationRunner {
    
        @PersistenceContext
        EntityManager entityManager;
    
        @Override
        public void run(ApplicationArguments args) throws Exception {
            Account account = new Account();
            account.setUsername("kimjunhyeung");
            account.setPassword("1234");
    
            Study study = new Study();
            study.setName("Spring Data JPA");
    
            account.getStudies().add(study); // 종속관계 관계 설정
            study.setOwner(account); //주인이 되는 쪽 관계 설정
    
            Session session = entityManager.unwrap(Session.class);
    
            session.save(account);
            session.save(study);
        }
    }

     

    Entity

    주인 관계를 설정하는 로직의 작성은 필수이며 종속관계의 로직은 필수는 아닙니다.
    그러나 객체지향적으로 활용하기 위해 주종 모두 관계를 설정해주는 것이 좋습니다.

    관계 설정 로직

    account.getStudies().add(study);
    study.setOwner(account);

    관계를 설정할 때 사용했던 로직입니다. 결과만 놓고 봤을 때는 주인쪽에 관계를 설정하면 이상 없지만 객체지향이기 때문에 양방향 관계를 설정해주어야합니다. 그래서 항상 같이 다니기 때문에 하나의 메소드로 묶어주면 편리합니다. 이 메소드를 컨비니언스(convinience) 메소드 라고 합니다.

    addStudy 메소드 생성

    public void addStudy(Study study) {
        this.getStudies().add(study);
        study.setOwner(this);
    }

    Account 클래스에서 Study를 추가할 때마다 관계를 설정하는 메소드를 생성합니다.
    여기서 this는 account를 가르킵니다.

    메소드 활용

    account.addStudy(study);

    애플리케이션 구동시 생성한 메소드만 호출해주면 관계 설정 로직이 구동됩니다.

    'Back-end > JPA' 카테고리의 다른 글

    JPA - FETCH  (0) 2020.06.30
    JPA - 엔티티 상태, Cascade  (0) 2020.06.30
    JPA - Value Mapping(밸류 매핑)  (0) 2020.06.30
    JPA - Entity Mapping(엔티티 매핑)  (0) 2020.06.30
    JPA - 프로젝트 세팅방법  (0) 2020.06.30

    댓글