-
[JPA] 연관관계프로그래밍/JPA 2021. 10. 20. 17:29반응형
이 글은 혼자 학습한 내용을 바탕으로 작성되었습니다.
틀리거나 잘못된 정보가 있을 수 있습니다.
댓글로 알려주시면 수정하도록 하겠습니다.
1. 연관관계
JPA의 연관관계는 3가지 키워드가 있다
- 방향
예를 들어 회원과 팀의 관계에서 회원 -> 팀 또는 팀 -> 회원과 같은 방향을 단방향 관계라고 한다.
회원 -> 팀, 팀 -> 회원과 같은 방향을 양방향 관계라고 한다.
방향의 경우 객체관계에만 존재한다.
테이블의 겨우는 항상 양방향 관계이다. - 다중성
다중성에는 [다대일, 일대다, 일대일, 다대다] 4가지 다중성이 있다.
회원과 팀의 관계에서 회원은 1개의 팀에만 속할 수 있는 경우는 회원(다) : 팀(일)인 다대일 관계가 된다.
팀과 회원의 관계에서 회원은 1개의 팀에만 속할 수 있는 경우는 팀(일) : 회원(다)인 일대다 관계가 된다.
회원과 팀의 관계에서 회원은 여러 팀에 속할 수 있는 경우는 회원(다) : 팀(다)인 다대다 관계가 된다.
회원과 사물함의 관계에서 회원은 1개의 사물함만 사용가능한 경우는 회원(일) : 사물함(일)인 일대일 관계가 된다. - 연관관계의 주인
객체를 양방향 관계로 만들면 연관관계의 주인을 정하여 주인만 연관관계의 키를 관리하도록 해야한다.
2. 객체와 테이블의 연관관계 차이
- 객체 관점
회원 객체는 필드(맴버변수)로 팀 객체와 연관관계를 맺는다.
회원 객체와 팀객체는 단방향 관계를 맺고있다.
회원의 객체에서 팀 객체로의 접근은 가능 하지만 반대로 팀 객체에서 회원으로의 접근은 불가능 하다. - 테이블 관점
회원 테이블은 외래 키로 팀 테이블과 연관관계를 맺는다.
회원 테이블과 팀 테이블은 양방향 관계를 맺고있다.
두 테이블은 외래 키를 가지고 서로 조인이 가능하다 회원 테이블에서 외래 키로 팀 테이블과 조인이 가능하며,
팀 테이블에서 외래 키로 회원 테이블과 조인이 가능하다. - 객체의 경우는 항상 단방향이며 테이블의 경우는 항상 양방향의 방향성을 가진다.
이러한 방향의 다름은 두 객체가 서로 참조를 하면 단방향 연관관계 2개를 통해 양방향 처럼 사용이 가능하다.
3. 엔티티와 테이블 관계 매핑
엔티티에 연관관계를 매핑하기 위해서는 다중성을 나타내는 어노테이션을 필수로 사용해야된다.
다중성을 나타내는 어노테이션 종류
- ManyToOne
- OneToMany
- ManyToMany
- OneToOne
외래 키로 매핑하고자 하는 경우 JoinColumn 어노테이션을 사용며 name 속성에는 매핑하고자 하는 외래 키의 이름을 지정한다.
JoinColumn 어노테이션은 생략이 가능하다.
JoinColumn 속성
속성명 기능 name 매핑할 외래 키 이름 referencedColumnName 외래 키가 참조하는 대상 테이블의 컬럼명 foreignKey 외래 키 제약조건을 직접 지정할 수 있다. 4. 단방향 연관관계 사용
- 회원 엔티티
@Entity public class Memeber{ @Id @Column(name="MEMBER_ID") private String id; private String username; @ManyToOne @JoinColumn(name="TEAM_ID") private Team team; public void setTeam(Team team){ this.team = team; } }
- 팀 엔티티
@Entity public class Team { @Id @Column(name="TEAM_ID") private String id; private String name; }
- 저장
회원 엔티티(member1)에 setTeam메소드를 통해 팀 엔티티를 참조 하도록 하고 저장했다.public void save(EntityManager em){ Team team1 = new Team("team1", "팀1"); em.persist(team1); Member member1 = new Member("member1", "회원1"); member1.setTeam(team1); em.persist(member1); Member member2 = new Member("member2", "회원2"); member1.setTeam(team1); em.persist(member1); }
JPA는 참조한 팀의 식별자(ID)를 외래 키로 사용해서 등록 쿼리를 생성하여 회원 엔티티를 저장 한다. - 조회
연관관계가 있는 인티티를 조회하는 방법은 크게 2가지가 있다.
1. 객체 그래프 탐색
2. 객체 지향 쿼리 사용 - 객체 그래프 탐색
member 엔티티의 getTeam 메소드를 사용해서 member 엔티티와 연관된 team 엔티티를 조회할 수 있다.
이처럼 객체를 통해 연관된 엔티티를 조회하는 것을 객체 그래프 탐색이라고 한다. - 객체 지향 쿼리 사용(JPQL)
jpql 문자열을 해석하면 회원과 팀의 관계를 가지고 있는 필드를 통해 Member와 Team을 조인하고 where절을 통해 검색조건으로 팀명이 팀1인 팀에 속한 회원만 검색했다.private static void jpqlQuery(EntityManager em){ String jpql = "select m from Memeber m join m.team t where " + "t.name=:teamName"; List<Member> resultList = em.createQuery(jpql, Memeber.class) .setParameter("teamName", "팀1"); .getResultList(); for(Member member : resultList) System.out.println(member.getUsername()); }
jpql을 상세히 보면 먼저 Member와 팀과의 연관관계를 맺고 있는 (m.team) 필드를 통해 Team과 조인을 한다.
그 이후 where 절을 통해 팀명이 파라미터로 전달 받은 팀명과 같은 (t.name=:teamName) 팀만 골라낸다. - 수정
수정의 경우 저장과 같은 메소드는 없다. 단순히 불러온 엔티티 member의 값만 변경하면 트랜잭션을 커밋할 때 플러시가 일어나면서 변경 감지 기능이 작동한다. 그 후 변경사항을 DB에 자동으로 반영한다.private static void update(EntityManager em){ Team team2 = new Team("team2", "팀2"); em.persist(team2); Member member = em.find(Member.class, "member1"); member.setTeam(team2); }
- 연관관계 제거
연관관계 제거의 경우 연관관계를 제거하고자 하는 엔티티값을 null로만 변경하면 된다.private static void delete(EntityManager em){ Memver member = em.find(Member.class, "member1"); member.setTeam(null); }
위 코드의 setTeam(null)을 한 것으로 JPA는 트랜잭션을 커밋할 때 변경 감지를 통해 외래 키의 값을 Null로 저장한다.
5. 양방향 연관관계 사용
- 회원 엔티티
@Entity public class Memeber{ @Id @Column(name="MEMBER_ID") private String id; private String username; @ManyToOne @JoinColumn(name="TEAM_ID") private Team team; public void setTeam(Team team){ this.team = team; } }
- 팀 엔티티
단방향 과는 다르게 List 컬렉션 members를 추가했다.@Entity public class Team { @Id @Column(name="TEAM_ID") private String id; private String name; @OneToMany(mappedBy="team") List<Member> members = new ArrayList<Member>(); }
그리고 팀과 회원의 관계는 일대다 관계 이므로 OneToMany 어노테이션을 사용했다.
또한 OneToMany 어노테이션의 속성으로 mappedBy를 사용하였는대 mappedBy는 양방향 매핑일 때 사용하는 속성으로 반대쪽(member의 팀 필드) 매핑의 필드명을 값으로 설정하면 된다.
- 조회
팀에서 회원 컬렉션으로 객체 그래프 탐색을 사용하여 회원들을 조회가능 하다.public void search(EntityManager em){ Team team = em.find(Team.class, "team1"); List<Member> members = team.getMembers(); for(Member member : members) System.out.println(member.getUsername()); }
- 저장, 수정, 제거
양방향 관계의 경우 연관관계의 주인이 정해진다.
하여 연관관계의 주인의 경우 조회, 저장, 수정, 제거 모두 가능 하지만 연관관계의 주인이 아닌 엔티티는 연관관계에 대한 조회만 가능하다.
그러므로 팀 엔티티의 회원 엔티티들의 조회는 가능하지만 저장, 수정, 제거는 불가능 하다.
반응형'프로그래밍 > JPA' 카테고리의 다른 글
[JPA] 예외 처리 (0) 2021.11.05 [JPA] 연관관계의 주인 (0) 2021.10.21 [JPA] Entity 매핑 (0) 2021.10.17 [JPA] 영속성 컨텍스트 (0) 2021.10.14 [JPA] 객체와 데이터베이스의 패러다임 불일치 (0) 2021.10.09 - 방향