JVM/JPA

@OneToMany

kyoulho 2023. 6. 12. 22:47

일대다 관계를 나타내는데 사용다.

 

데이터베이스 테이블의 다대일, 일대다 관계에서는 항상 다 쪽이 외래 키를 가진다.

JPA에서는 외래키를 가지고 있는 엔티티가 연관관계의 주인이라고 하며 외래키를 관리한다.

주인이 아닌 반대편은 읽기만 가능하고 외래키를 변경하지는 못한다.

 

속성 기능 기본값
mappedBy 엔티티의 PK가 FK로 사용되고 있는 테이블의 필드명을 지정한다.
연관관계의 주인이 아니라는 설정이기도 하다.
 
양방향 매핑이 아닌 일대다 단방향 매핑일 경우 필드 위에 @JoinColumn을 명시해야한다. 그렇지 않으면 JPA는 조인 테이블 전략을 기본으로 사용해서 매핑한다. 일대다 단방향 매핑은 객체가 관리하는 외래 키가 다른 테이블에 있기 때문에 성능 문제와 관리의 부담이 있다.
일대다 단방향 매핑 대신에 다대일 양방향 매핑을 사용하자!!

 

양방향 매핑 예제

@Entity
@Setter @Getter
public class Team {
    @Id
    @Column(name = "TEAM_ID")
    private String id;

    private String name;
    
    @OneToMany(mappedBy="team")
    private List<Member> members = new ArrayList();
}

@Entity
@Setter @Getter
public class Member { // 연관관계의 주인
    @Id
    @Column(name = "MEMBER_ID")
    private String id;

    @ManyToOne
    @JoinColumn(name = "TEAM_ID")
    private Team team;
}

 

주의

해당 코드는 FK에 null이 들어가게 되는 문제가 있는 코드이다.

주인이 아닌 곳에 입력된 값은 데이터베이스에 저장할 때 무시된다.

var team = new Team();
var member = new Member();

team.getMembers.add(member);

memberReposity.save(member);
teamRepository.save(team);

 

개선

객체의 양방향 연관관계를 양쪽 모두에게 맺어주는 것이 안전하다.

아래 코드처럼 관계를 해제하고 맺어주는  setter를 쓰는 것을 권장한다.

@Entity
@Setter @Getter
public class Member { // 연관관계의 주인
    @Id
    @Column(name = "MEMBER_ID")
    private String id;

    @ManyToOne
    @JoinColumn(name = "TEAM_ID")
    private Team team;
    
    public void setTeam(Team team){
    	if(this.team != null){
        	this.team.getMembers().remove(this);
    	} 
        this.team = team;
        
        if(!this.team.getMembers().contains(this)){
            this.team.getMembers().add(this);
        }
    }
}

'JVM > JPA' 카테고리의 다른 글

@ManyToMany  (0) 2023.06.16
@OneToOne  (0) 2023.06.16
@ManyToOne, @JoinColumn  (0) 2023.06.12
@Access  (0) 2023.06.11
@Transient  (0) 2023.06.11