아카이브

[스프링 데이터 JPA] JPA 프로그래밍 4. 1대다(관계) 맵핑 본문

Spring/스프링 데이터 JPA

[스프링 데이터 JPA] JPA 프로그래밍 4. 1대다(관계) 맵핑

주멘이 2021. 1. 10. 21:49

관계에는 항상 두 엔티티가 존재합니다.

  • 둘 중 하나는 그 관계의 주인(owning)이고
  • 다른 쪽은 종속된(non-owning) 쪽입니다.
  • 해당 관계의 반대쪽 레퍼런스를 가지고 있는 쪽이 주인.

단방향에서의 관계의 주인은 명확하다

  • 관계를 정의한 쪽이 그 관계의 주인입니다. 단방향 @ManyToOne
  • 기본값은 FK 생성

Study 도메인 클래스

public class Study {
    @Id
    @GeneratedValue
    private Long id;

    private String name;

    @ManyToOne // 어떤 study를 만든 사람은 여러 개를 만들 수 있다.   
    // 단방향에서의 관계의 주인은 관계를 정의한 쪽이다.
    private Account owner;
}

@ManyToOne으로 Account의 PK를 참조하는 owner_id FK를 생성한 모습

단방향 @OneToMany

  • 기본값은 조인 테이블 생성

Account 도메인 클래스

public class Account { 
	... 생략

    @OneToMany(mappedBy = "owner")  // 한 Account는 여러 study를 만들 수 이있다. 
    							 	//끝쪽이 Many면 Collection이다
    private Set<Study> studies = new HashSet<>();
    
    ... 생략

}

account_studies라는 Mapping 테이블을 만든다.

양방향

  • FK 가지고 있는 쪽이 오너(Study) 따라서 기본값은 @ManyToOne 가지고 있는 쪽이 주인(Study)
  • 주인이 아닌 쪽(@OneToMany 쪽)에서 mappedBy 사용해서 관계를 맺고 있는 필드를 설정해야 함(Study의 owner 필드)

양방향

  • @ManyToOne (관계를 정의하는 이쪽이 주인)

    자기 자신 안에 적용한 Entity에 대한 Foerign key를 생성

  • @OneToMany(mappedBy)
  • 주인한테 관계를 설정해야 DB에 반영이 됩니다. 

 

Study 도메인 클래스 (@ManyToOne)

public class Study {
    @Id
    @GeneratedValue
    private Long id;

    private String name;
    
    @ManyToOne // 어떤 study를 만든 사람은 여러 개를 만들 수 있다.   
    		   // 단방향에서의 관계의 주인은 관계를 정의한 쪽이다.
    private Account owner;	// Account의 pk를 참조하는 owner_id FK 컬럼을 만든다
}

 

Account 도메인 클래스(@OneToMany)

public class Account {  
    @Id             // ID로 쓴다 (식별자)
    @GeneratedValue // 자동생성값, DB마다 생성전략이 다를 수 있다.
    private Long id;

    @Column(nullable = false, unique = true)  
    private String username;

    private String password;

    @Temporal(TemporalType.TIMESTAMP)
    private Date created = new Date();

    private String yes;

    @Transient 
    private String no;

    @Embedded
    @AttributeOverrides({
            @AttributeOverride(name = "street", column = @Column(name = "home_street"))
    })
    private Address address;

    @OneToMany(mappedBy = "owner")  // 한 Account는 여러 study를 만들 수 이있다. 
    							    //끝쪽이 Many면 Collection이다.
                                    // Study의 @ManyToOne인 private Account owner를 지정해서 알려준다.
    private Set<Study> studies = new HashSet<>();

	/* 관계를 관리하는 Convinience method */
    public void addStudy(Study study) {
        this.getStudies().add(study);    // optional이지만 객체지향적으로 서로에 대한 관계를 넣어줄 것
        study.setOwner(this);
    }
	/* 관계를 관리하는 Convinience method */
    public void removeStudy(Study study) {
        this.getStudies().remove(study);    // optional이지만 객체지향적으로 서로에 대한 관계를 넣어줄 것
        study.setOwner(null);
    }
}

 

양방향 관계 설정 한 묶음으로 처리하기

convenience 메서드 : 관계를 관리하는 메서드

    /* 기존 로직*/	
    account.getStudies().add(study);
    study.setOwner(account);
    
    /* 한 묶음으로 Convinience method를 통한 로직 */
    public void addStudy(Study study) {
        this.getStudies().add(study);    // optional이지만 객체지향적으로 서로에 대한 관계를 넣어줄 것
        study.setOwner(this);
    }
    public void removeStudy(Study study) {
        this.getStudies().remove(study);    // optional이지만 객체지향적으로 서로에 대한 관계를 넣어줄 것
        study.setOwner(null);
    }