[Spring_Boot] JPA - 연관관계 매핑(단방향),예제

최현석·2022년 12월 7일
0

Spring_Boot

목록 보기
21/31

🧩 연관관계 매핑

  • 객체와 테이블 연관관계의 차이를 이해
  • 객체의 참조와 테이블의 외래 키를 매핑
  • 연관관계 주인(Owner) : 객체 양방향 연관관계는 관리가 필요
  • 테이블은 외래키로 조인을 사용해서 연관된 테이블을 찾는다.
  • 객체는 참조를 사용해서 연관된 객체를 찾는다.
  • 테이블과 객체 사이에는 이런 큰 간격이 있다.
  • 객체를 테이블에 맞춰 데이터 중심으로 모델링하면, 협력 관계를 만들 수 없다.


  • 회원과 주문의 관계 : 회원은 여러 번 주문 할 수 있다. → 일대다 관계(1:N)
  • 주문과 상품의 관계 : 주문 시 여러 상품을 선택할 수 있다. 반대로 상품도 여러 번 주문될 수 있다. → 다대다 관계(N:M)
  • 주문과 주문 상품의 관계 : 하나의 주문에 여러 상품을 선택할 수 있다 → 일대다 관계(1:N)
  • 주문 상품과 상품의 관계 : 하나의 상품이 여러 주문 상품에 선택될 수 있다. → 다대일 관계(N:1)


🧩 예제

  • 회원 - 팀
  • 회원은 하나의 팀에만 소속될 수 있다.
  • 회원과 팀은 다대일 관계다.

1) 객체를 테이블에 맞추어 모델링( 연관관계가 없는 객체)

  • 테이블에서 team_id와 team_id가 연결되어 있다면
  • 객체에서는 teamId -> id 연결이 걸려있어야 한다.

Member

Entity
@Getter @Setter
public class Member {

	@Id @GeneratedValue
	@Column(name = "MEMBER_ID")
	private Long id;
	
	@Column(name = "USERNAME")
	private String name;
	
	@Column(name = "TEAM_ID")
	private Long teamid;
}

Team

@Entity
@Getter @Setter
public class Team {
	
	@Id @GeneratedValue
	@Column(name = "TEAM_ID")
	private Long id;
	private String name;
	
}

JpaMain

  • DB에 저장, 조회하는 로직

  • DB관계 상 team이 만들어진 뒤 member가 할당

  • member1 이 소속된 팀 정보를 조회하려면 어떻게 해야하는가?

    • 매번 member를 우선 조회한 뒤 외래키를 뽑아 그것으로 팀의 정보를 조회해야한다. → 협력관계를 만들 수 없다.
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");
			// 영속상태가 되면, PK의 값이 세팅이 된 후 영속상태 된다.
			em.persist(team);
			
			Member member = new Member();
			member.setName("member1");
			// team이 영속성컨텍스트 안에있므로 DB에서 select해올 필요가 없다
			member.setTeamid(team.getId());
			em.persist(member);
			
			// select
			// 어느팀 소속인지 알고 싶을 때 jpa(영속성) or db에게 계속 물어봐야 한다.
			// 최종적으로 Member가 속해있는 팀의 이름이 궁금하다!!
			// db에서는 left join으로 알수있다.
			// 해당 객체에 해당 키값을 넘겨서 findMember에 담아온다.
			Member findMember = em.find(Member.class, member.getId());
			// findMember에 팀의 아이디를 획득한 다음
			Long findTeamid = findMember.getTeamid();
			// 팀의 아이디를 가지고 팀객체에서 find해서 팀의 정보가 나오게되고
			Team findTeam = em.find(Team.class, findTeamid);
			// 팀의 정보에서 name을 가져오면 찾고자하는 member의 팀이름을 출력
			System.out.println("findTeam : " + findTeam.getName());
		
			// 영속성으로 들어감
			tx.commit();
		}catch (Exception e) {
			tx.rollback();
		}finally {
			em.close();
			emf.close();
		}
		
	}

  • 중간에 위치한 이유는 영속성 컨텍스트에 먼저 보내고, db에 insert하기 때문이다.

2) 객체 지향 모델링 (객체 연관관계 사용)

  • 1(Team) 대 다(Member) 관계
  • Member라는 클래스는 Team이라는 클래스를 참조시켜버림

Member

  • @ManyToOne : 여기에선 Team이 하나
  • @JoinColumn : 관계 컬럼을 적어준다. TEAM_ID와 조인해야 한다.
  • @ManyToOne @JoinColumn 을 통해 멤버(Member)에서 (Team)을 참조하도록 했다.
@Entity
@Getter @Setter
public class Member {

	@Id @GeneratedValue
	@Column(name = "MEMBER_ID")
	private Long id;
	
	@Column(name = "USERNAME")
	private String name;
	
	@ManyToOne
	@JoinColumn(name = "TEAM_ID")
	private Team team;
}

  • 대상이 되는 컬럼의 명칭을 매핑 시켜줘야 한다.

JpaMain

			Team team = new Team();
			team.setName("TeamA");
			// 영속상태가 되면, PK의 값이 세팅이 된 후 영속상태 된다.
			em.persist(team);
			
			Member member = new Member();
			member.setName("member1");
            // Member에서 Team을 객체로 자체로 받아온다.
            // 객체(Team) 자체를 세팅
			member.setTeam(team);
			em.persist(member);
			
			// 강제로 DB 쿼리를 보고싶을때
			em.flush();
			em.clear();
			
			// select 조회
			// find시에 1차캐시에서 가지고 와서 select문이 없다.
			Member findMember = em.find(Member.class, member.getId());
            // 멤버세서 팀 객체를 통으로 받아와서 꺼내온다.
			Team findTeam = findMember.getTeam();
			System.out.println("findTeam : " + findTeam.getName());
			
			// 영속성으로 들어감
			tx.commit();
  • 강제로 DB 쿼리를 보고싶을 때 사용
    em.flush();
    em.clear();

0개의 댓글