JPA

JPA 연관관계

으엉어엉 2024. 8. 21. 17:49
728x90
  • 방향(Direction): 단방향, 양방향
  • 다중성(Multiplicity): 다대일(N:1), 일대다(1:N), 일대일(1:1), 다대다(N:M) 이해
  • 연관관계의 주인(Owner).. 어려운 내용: 객체 양방향 연관관계는 관리 주인이 필요 JPA계의 포인터

 

import jakarta.persistence.*;

@Entity
@TableGenerator(
        name = "MEMBER_SEQ_GENERATOR",
        table = "MY_SEQUENCES",
        pkColumnValue = "MEMBER_SEQ", allocationSize = 1)
public class Member {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE,
            generator = "MEMBER_SEQ_GENERATOR")
    @Column(name = "MEMBER_ID")
    private Long id;

    @Column(name = "USERNAME")
    private String username;

//    @Column(name = "TEAM_ID")
//    private Long teamId;

    @ManyToOne //member은 many , team은 one
    @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 setTeam(Team team) {
        this.team = team;
    }
}

 

ManyToOne이랑 JoinColumn을 하게 되면 아래와 같은 맵핑이 된다.

 

        try {
            Team team = new Team();
            team.setName("TEAMA");
            em.persist(team);

            Member member = new Member();
            member.setUsername("member1");
            member.setTeam(team);

            em.persist(member);

            Member findMember =  em.find(Member.class, member.getId());
            Team findTeam = findMember.getTeam();

            tx.commit(); //이것을 한 시점에 데이터베이스 쿼리에 등록
        }catch (Exception e) {
            tx.rollback();
        }finally {
            em.close();
        }
        emf.close();

 

이런 식으로 Team에서 바로 findMember을 할 수 있다.

 

 

 

 


 

양방향 연관관계 

ex) 왼쪽 단방향                                                                               오른쪽 양방향

 

양방향 연관관계란? 양쪽으로 참조해서 갈 수 있게 만드는 것을 말한다.

 

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

로 표현한다.

mappedBy = team이라는 게 없어도 되는 게 아니야? 할 수 있다.

하지만 객체와 테이블 간에 연관관계를 맺는 차이를 이해해야 한다.

그렇다면 이 차이가 뭐냐 ?  

예시: 

• 객체 연관관계 = 2개

  • 회원 -> 팀 연관관계 1개(단방향)
  • 팀 -> 회원 연관관계 1개(단방향)

• 테이블 연관관계 = 1개

  • 회원 <-> 팀의 연관관계 1개(양방향)

양방향이란 단방향이 두개인 것이다. 고로 양방향을 만들려면 단방향을 두 개를 만들어야 한다.  

 

테이블은 외래 키 하나로 두 테이블의 연관관계를 관리한다. Join을 통해... 

mappedBy = "team"

을 통해  team이랑 연결되어 있음을 알려준다.

 

Member findMember =  em.find(Member.class, member.getId());
List<Member> members = findMember.getTeam().getMembers();

for (Member m : members) {
    System.out.println("m = " + m.getUsername());
}

을 통해 Member을 알 수 있다. 

객체는 단방향이 좋긴 하다. 양방향을 하면 신경 쓸 것들이 많이 생기기 때문이다.

 

 

양방향 매핑 규칙

  • 객체의 두 관계중 하나를 연관관계의 주인으로 지정
  • 연관관계의 주인만이 외래 키를 관리(등록, 수정)
  • 주인이 아닌쪽은 읽기만 가능
  • 주인은 mappedBy 속성 사용 X
  • 주인이 아니면 mappedBy 속성으로 주인 지정

외래키가 있는곳을 주인으로 정하자.

 

 

 

 Team team = new Team();
  team.setName("TeamA");
  em.persist(team);
  Member member = new Member();
  member.setName("member1");
  team.getMembers().add(member); 
  //연관관계의 주인에 값 설정 
  member.setTeam(team);
  em.persist(member);
team.getMembers().add(member);

 

양 방향은 양 쪽 다 값을 넣어주는 것이 좋다.

Meber 클래스에 아래 코드를 셋팅한다면 헷갈릴 일이 없어진다.

    public void setTeam(Team team) {
        this.team = team;
        team.getMembers().add(this);
    }

 

 

Control에서 Entity API반환하지 말자. 

무한루프가 생기거나 Entity변경하기가 힘들 수 있다. 

728x90

'JPA' 카테고리의 다른 글

JPA 상속관계 맵핑  (0) 2024.08.22
JPA 연관관계 매핑  (0) 2024.08.22
JPA 엔티티 매핑  (0) 2024.08.15
JPA 플러시  (0) 2024.08.15
JPA 영속성  (0) 2024.08.15