[Spring JPA] 양방향 매핑 시 연관관계 메서드 설정
결론
양방향 매핑시 연관관계를 양쪽에서 맺어주지 않으면, 한 트랜잭션 내에서 제대로 조회가 되지 않을 수 있다. 연관관계 메서드를 설정하자.
상황
상황을 간략히 아래 예시로 표현해보았다.
1. 부모 트랜잭션 A, 자식 트랜잭션 B, 자식 트랜잭션 C가 있는 상황에서 실행 순서는 A -> B -> C 순서로 진행된다.
2. 자식 트랜잭션 B에서 생성한 객체를 자식 트랜잭션 C에서 사용하고자 한다.
3. 자식 트랜잭션 C에서 객체를 조회하는 과정에서 에러가 발생했다.
// 부모 트랜잭션 A
@Transactional
public void parentMethod() {
childOneMethod();
childTwoMethod();
}
// 자식 트랜잭션 B
@Transactional
public void childOneMethod() {
Member member = new Member("m1", "Daisy");
Team team = new Team("t1", "Seoul");
member.setTeam(team);
...
}
// 자식 트랜잭션 C
@Transactional
public void childTwoMethod() {
Team team = repository.findByName("Seoul");
team.getMembers(); // 에러 발생
...
}
@Entity
public class Member {
@Id
@GeneratedValue
private Long id;
@ManyToOne
@JoinColumn(name = "TEAM_ID") // 연관관계의 주인 (외래키를 저장하는 곳)
private Team team;
}
@Entity
public class Team {
@Id
@GeneratedValue
private Long id;
@OneToMany(mappedBy = "team") // Member.team 연관관계의 주인
List<Member> members = new ArrayList<Member>();
}
트러블 슈팅
- Spring 기본 설정에 의해 자식 트랜잭션은 부모 트랜잭션을 그대로 이어받고, 따라서 commit 역시 부모 트랜잭션과 같은 시점에 이루어진다. 따라서, 자식 트랜잭션 B에서 생성된 객체는 아직 DB에 commit되지 않은 상태이다.
- 따라서 Team의 members는 아직 연관 관계가 설정되지 않은 상태이고, 같은 트랜잭션 내에서 조회할 시에 null 에러가 날 수 밖에 없다.
예시
// Team에는 연관 관계 설정을 하지 않았다.
Team team = new Team();
team.setName("TeamA");
em.persist(team);
Member member = new Member();
member.setName("member1");'
// Member에서는 연관 관계 설정을 했다.
member.setTeam(team);
em.persist(member)
Team findTeam = em.find(Team.class, team.getId());
// 커밋하지 않았기 때문에 조회하면 null이 나온다.
findTeam.getMembers();
해결방안
원칙적으로는 연관관계의 주인쪽인 Member에서만 연관관계를 맺어도, 양방향으로 사용이 가능하다. 하지만, 양쪽에서 연관관계를 설정해주지 않으면 이와 같이 한 트랜잭션 내에서 제대로 조회가 되지 않는 문제가 발생한다. 이러한 상황을 방지하기 위해서는 연관관계 메서드를 사용해 양방향으로 연관관계를 매핑해줘야 한다.
@Entity
public class Member {
@Id
@GeneratedValue
private Long id;
@ManyToOne
@JoinColumn(name = "TEAM_ID") // 연관관계의 주인 (외래키를 저장하는 곳)
private Team team;
/* 연관관계 메서드 설정 */
public void setTeam(Team team){
this.team=team;
team.getMembers().add(this);
}
}
Reference: https://jiwondev.tistory.com/227
Author And Source
이 문제에 관하여([Spring JPA] 양방향 매핑 시 연관관계 메서드 설정), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@titu/Spring-Transaction-중첩-사용Transactional저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)