아래의 코드가 있다고 하자
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_ID가 null로 들어간 것을 알 수 있다. 이유는 이전 게시물에서 말했듯 team은 읽기 전용이기때문이다.
반대로 연관관계 주인에 값을 넣게 되면,
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");
// 주의할 부분
// team.getMembers().add(member);
em.persist(team);
Member member = new Member();
member.setUsername("member1");
// 주인으로 값을 없었다.
member.setTeam(team);
em.persist(member);
em.flush();
em.clear();
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
}
emf.close();
}
}
올바르게 값이 들어갔다.
여기서 잘 된것 같지만 주의할 점이 또 있다.
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("member1");
member.setTeam(team);
em.persist(member);
// em.flush();
// em.clear();
Team findTeam = em.find(Team.class, team.getId());
List<Member> members = findTeam.getMembers();
System.out.println("====================");
for (Member m : members) {
System.out.println("m = " + m.getUsername());
}
System.out.println("====================");
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
}
emf.close();
}
}
이 경우인데
flush와 clear를 진행하지 않는다고 하자, 그랬을 때 코드의 결과를 보면
아무것도 출력이 되지 않는 것을 알 수 있다. 그 이유는,
Team team = new Team();
team.setName("TeamA");
em.persist(team);
현재 team은 위 코드 그대로 1차 캐시에만 올라가 있기 때문이다. 즉,
순수한 객체 상태라고 보면된다.
그래서 결론은 flush나 clear를 따로 할 것이 아니라면, 객체는 양방향 모두 값을 넣어주는 것이 맞다.
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("member1");
member.setTeam(team);
em.persist(member);
// 이 부분도 추가하는 것이 맞다.
team.getMembers().add(member);
Team findTeam = em.find(Team.class, team.getId());
List<Member> members = findTeam.getMembers();
System.out.println("====================");
for (Member m : members) {
System.out.println("m = " + m.getUsername());
}
System.out.println("====================");
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
}
emf.close();
}
}
사실 이렇게 두 엔티티에 모두 넣을 때 둘 다 작성하는 것이 귀찮을 수 있으므로,
member.setTeam(team);
// 위 아래 모두 추가하는 것 보다는?
team.getMembers().add(member);
두 가지, Team에서 추가할 것인지 아니면 Member에서 추가하는 방법이 있다.
Member에서 추가한다면,
@Entity // Entity는 JPA에서 관리하는 것임을 나타냄
public class Member {
@Id @GeneratedValue
@Column(name = "MEMBER_ID")
private Long id;
@Column(name = "USERNAME")
private String username;
@ManyToOne
@JoinColumn(name = "TEAM_ID")
private Team team;
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public Team getTeam() {
return team;
}
// 이 부분 추가
public void changeTeam(Team team) {
this.team = team;
team.getMembers().add(this);
}
public void setTeam(Team team) {
this.team = team;
}
}
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("member1");
// 이렇게 바꿈
member.changeTeam(team);
em.persist(member);
Team findTeam = em.find(Team.class, team.getId());
List<Member> members = findTeam.getMembers();
System.out.println("====================");
for (Member m : members) {
System.out.println("m = " + m.getUsername());
}
System.out.println("====================");
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
}
emf.close();
}
}
이렇게 할 것인지, 아니면 Team에서 추가하는 방법인
@Entity
public class Team {
@Id @GeneratedValue
@Column(name = "TEAM_ID")
private Long id;
private String name;
@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<>();
// 추가 코드
public void addMember(Member member) {
member.setTeam(this);
members.add(member);
}
public List<Member> getMembers() {
return members;
}
public void setMembers(List<Member> members) {
this.members = members;
}
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;
}
}
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("member1");
em.persist(member);
// 추가 코드
team.addMember(member);
Team findTeam = em.find(Team.class, team.getId());
List<Member> members = findTeam.getMembers();
System.out.println("====================");
for (Member m : members) {
System.out.println("m = " + m.getUsername());
}
System.out.println("====================");
tx.commit();
} catch (Exception e) {
tx.rollback();
} finally {
em.close();
}
emf.close();
}
}
이 방법이 있는데 둘 중 하나로 쓰면 된다.
조회 되는 것을 확인할 수 있다.
[ JPA ] 상속관계 매핑 (0) | 2022.01.15 |
---|---|
[ JPA ] persist 와 id값 (0) | 2022.01.09 |
[ JPA ] 양방향 연관관계(1) - mappedBy (0) | 2022.01.07 |
[ JPA ] 단방향 연관관계 (0) | 2021.12.30 |
[ JPA ] @Entity (0) | 2021.12.19 |