상황
Member:Team = N:1의 관계이다. 양방향 연관 관계의 주인은 Member.team이다.
잘못된 경우(연관관계 주인이 아닌 곳에서 값을 입력하는 경우)
package hellojpa;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try{
Member member = new Member();
member.setUserName("member1");
em.persist(member);
Team team = new Team();
team.setName("TeamA");
//역방향(연관관계 주인이 아닌 방향)만 연관관계 설정
team.getMembers().add(member);
em.persist(team);
em.flush();
em.clear();
tx.commit();
} catch(Exception e) {
tx.rollback(); //오류 발생 시 롤백
} finally {
//종료
em.close();
}
emf.close();
}
}
지금 위의 경우는 가짜 매핑된 team.members에서 update를 하고 있다. 가짜 매핑된 부분에서는 뭔 짓을 하든 DB에는 반영이 되지 않는다. 가짜 매핑된 team.members에 member를 add()하더라도 member.team에는 연관관계가 매핑되지 않아MEMBER 테이블의 TEAM_ID가 null인 것을 볼 수 있다.
올바른 경우
package hellojpa;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.EntityTransaction;
import javax.persistence.Persistence;
public class JpaMain {
public static void main(String[] args) {
EntityManagerFactory emf = Persistence.createEntityManagerFactory("hello");
EntityManager em = emf.createEntityManager();
EntityTransaction tx = em.getTransaction();
tx.begin();
try{
Team team = new Team();
team.setName("TeamA");
em.persist(team);
Member member = new Member();
member.setUserName("MemberA");
// 연관 관계주인에서 매핑
member.setTeam(team);
em.persist(member);
em.flush();
em.clear();
// team 조회
Team findTeam = em.find(Team.class, team.getId());
List<Member> members = findTeam.getMembers();
// team.members 출력
for (Member m : members) {
System.out.println("m = " + m.getUserName());
}
tx.commit();
} catch(Exception e) {
tx.rollback(); //오류 발생 시 롤백
} finally {
//종료
em.close();
}
emf.close();
}
}
결론
양방향 연관관계인 경우에는 순수한 객체 관계를 고려하여 양쪽모두에 값을 넣어주자.
Team team = new Team();
team.setName("TeamA");
em.persist(team);
Member member = new Member();
member.setUserName("MemberA");
member.setTeam(team); // 값 주입
em.persist(member);
team.getMembers().add(member); // 값 주입
tx.commit();
근데 항상 이렇게 일일히 넣어주기 힘드니까 연관관계 편의 메소드를 만들자.
연관관계 편의 메소드
package hellojpa;
import lombok.Getter;
import lombok.Setter;
import javax.persistence.*;
@Entity
@Getter
@Setter
public class Member {
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
@Column(name = "USERNAME", nullable = false)
private String userName;
@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;
// 연관관계 편의 메소드
public void changeTeam(Team team) {
this.team = team;
team.getMembers().add(this); //setTeam()시 자동으로 반대편에도 값이 주입됨
}
}
'Spring > JPA' 카테고리의 다른 글
JPA- 상속관계 매핑 (0) | 2023.03.12 |
---|---|
JPA- 다대일, 일대일 (0) | 2023.03.08 |
JPA- 연관관계 매핑 (0) | 2023.03.05 |
JPA- 중요! 엔티티 매핑 (0) | 2023.02.28 |
JPA- flush와 영속성 관리 (0) | 2023.02.28 |