연관관계 매핑

방세현·2023년 3월 27일
0

jpa

목록 보기
2/8
post-thumbnail

데이터베이스에서는 두 테이블의 연관관계를 설정하면 외래키를 통해 서로 조인해서 참조하는 구조로 생성되지만 JPA를 사용하는 객체지향 모델링에서는 엔티티 간 참조방향을 설정할 수 있다.

  • 단방향: 두 엔티티의 관계에서 한쪽의 엔티티만 참조하는 형식
  • 양방향: 두 엔티티의 관계에서 각 엔티티가 서로의 엔티티를 참조하는 형식

연관관계가 설정되면 한 테이블에서 다른 테이블의 기본값을 외래키로 갖기 된다. 일반적으로 외래키를 가진 테이블이 그 관계의 주인이 되며, 주인은 외래키를 사용할 수 있으나 상대 엔티티는 읽는 작업만 수행할 수 있다.


일대일 매핑


@Entity(name = "parent")
public class Parent {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id; //여기는 parent 의 id
}

@Entity(name = "child")
public class Child {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id; //여기는 child 의 id 
    
    @OneToOne
    @JoinColumn(name = "parent_id") //child에 지정되있는 FK parent_id기준으로 parent조회 
    private Parent parent;
}

@OneToOne 어노테이션은 다른 엔티티 객체(ProductEntity)를 필드로 정의했을 때 일대일 연관관계로 매핑하기 위해 사용된다. 뒤이어 @JoinColumn 어노테이션을 사용해 매핑할 외래키를 설정한다.

JPA에서 관계를 정의할때 부모 Entity 객체에 정의된 PK와 자식 Entity객체에 정의된 FK를 기준으로 정의할 수 있는데 @OneToOne 어노테이션이 위치하는 곳은 기본적으로 FK가 있는쪽, 즉 자식쪽 Entity 객체쪽이 된다.

OneToOne 관계를 맺었을때 디폴트 설정으로 FetchType 이 EAGER 로 설정되어 있어 자식 Entity 를 조회 했을때 자동으로 부모 Entity 를 조회해 옵니다. 이때 바로 부모 Entity 를 사용할 필요가 없다면 속도를 위해 FetchType 을 LAZY 로 설정할 수 있습니다. FetchType 을 LAZY 로 지정하면 지정된 Entity 객체를 미리 가지고 있는 것이 아니라 Entity 객체를 사용하려고 할때 그 즉시 데이타를 데이터베이스에서 가지고 옵니다.

@Entity(name = "parent")
public class Parent {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id; //여기는 parent 의 id
}

@Entity(name = "child")
public class Child {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id; //여기는 child 의 id 
    
    @OneToOne(fetch = FetchType.LAZY) //사용시점에 조회가 됨
    @JoinColumn(name = "parent_id") //child 에 지정되어 있는 FK parent_id 기준으로 parent 조회 
    private Parent parent;
}

일대다, 다대일 매핑


@OneToMany는 데이터를 바라보는 주체가 부모 Entity이며 하나의 부모 Entity데이터와 연관이 있는 여러개의 자식 Entity 데이터를 사용한다는 의미입니다.

이때 부모 Entity에서 @OneToMany 어노테이션을 지정하게 되며, JPA 관계 중 유일하게 @어노테이션이 자식Entity이 아닌 부모 Entity에 위치하게 됩니다. 또한 속도를 위해 기본적으로 FetchType 설정이 LAZY로 설정되어 있습니다.

@Entity(name = "parent")
public class Parent {
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private Long id;
   
   @OneToMany
   @JoinColumn(name = "parent_id") //child 테이블에 있는 parent_id FK 
   private List<Child> childList;
}

@Entity(name = "child")
public class Child {
   @Id
   @GeneratedValue(strategy = GenerationType.IDENTITY)
   private Long id;
}

아래는 응용코드를 가져왔다. Member은 부모Entity이고 Phone은 자식 Entity이다.

package jpa3;

import java.util.List;

import javax.transaction.Transactional;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.CommandLineRunner;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;

@SpringBootApplication
public class Jpa3Application implements CommandLineRunner{

	@Autowired
	private MemberRepository mr;
	
	@Autowired
	private PhoneRepository pr;
	
   public static void main(String[] args) {
       SpringApplication.run(Jpa3Application.class, args);
   }

	@Override
	public void run(String... args) throws Exception {
		
		Member first = new Member("Jung"); // (1)
		first.addPhone(new Phone("010-XXXX-XXXX"));
		first.addPhone(new Phone("010-YYYY-YYYY"));
		
		Member second = new Member("Dong");
		second.addPhone(new Phone("010-ZZZZ-ZZZZ"));
		
		Member third = new Member("Min"); // (2)
		
		mr.save(first); // (3)
		mr.save(second);
		mr.save(third); // (4)
		
		List<Member> list = mr.findAll(); // (5)
		
		for( Member m : list ){
			System.out.println(m.toString());
		} // (6)
		
		mr.deleteAll(); // (7)
	}
}

출처

@ManyToOne

@Entity(name = "parent")
public class Parent {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
}

@Entity(name = "child")
public class Child {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    @ManyToOne
    @JoinColumn(name = "parent_id")
    private Parent parent;
}

0개의 댓글