관계 매핑 관계 매핑에선 항상 두 엔티티가 존재해야합니다. 주종관계 를 가지고 있으며 반대쪽 레퍼런스를 가진쪽이 주인 관계가 됩니다. 두 엔티티 클래스가 필요하기 때문에 기존 Account 클래스, 추가적으로 Study 클래스를 생성합니다. 여기서 Study는 Account가 Study를 다수로 생성할 수 있는 개념입니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 @Entity public class Study { @Id @GeneratedValue private Long id; private String name; 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; } }
단방향
관계를 정의한 쪽이 그 관계의 주인입니다.(@ManyToOne)
기본값은 FK가 생성됩니다.
기본값은 조인 테이블을 생성합니다.
@OneToMany로 매핑시 JOIN 테이블로 매핑됩니다.
@ManyToOne 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 @Entity public class Study { @Id @GeneratedValue private Long id; private String name; @ManyToOne private Account owner; public Account getOwner () { return owner; } public void setOwner (Account owner) { this .owner = owner; } 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; } }
스터디는 하나의 계정이 복수로 만들 수 있습니다. 그러므로 @ManyToOne 을 사용합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 @Component @Transactional public class JpaRunner implements ApplicationRunner { @PersistenceContext EntityManager entityManager; @Override public void run (ApplicationArguments args) throws Exception { Account account = new Account(); account.setUsername("kimjunhyeung" ); account.setPassword("1234" ); Study study = new Study(); study.setName("Spring Data JPA" ); study.setOwner(account); Session session = entityManager.unwrap(Session.class); session.save(account); session.save(study); } }
Study를 Account에 추가하는 코드를 작성합니다. owner라고 값을 주었지만 Account의 PK 를 참고하는 owner_id라는 FK 가 생성됩니다.
@OneToMany 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 @Entity public class Account { @Id @GeneratedValue private Long id; @Column (nullable = false , unique = true ) private String username; private String password; @OneToMany private Set<Study> studies = new HashSet<>(); }
Account는 여러개의 Study를 가질 수 있기 때문에 Set에 담아서 @OneToMany 를 선언합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 @Component @Transactional public class JpaRunner implements ApplicationRunner { @PersistenceContext EntityManager entityManager; @Override public void run (ApplicationArguments args) throws Exception { Account account = new Account(); account.setUsername("kimjunhyeung" ); account.setPassword("1234" ); Study study = new Study(); study.setName("Spring Data JPA" ); account.getStudies().add(study); Session session = entityManager.unwrap(Session.class); session.save(account); session.save(study); } }
Set에 study를 add해줍니다. 2개가 아닌 3개의 테이블이 생겼는데 account_studies는 JOIN 테이블 로서 각 테이블의 PK를 가지고 있게 됩니다.
양방향
FK를 가지고 있는 쪽이 주인입니다. 따라서 기본값은 @ManyToOne 가지고 있는 쪽이 주인입니다.
주인이 아닌쪽(@OneToMany쪽)에서 mappedBy 사용해서 관계를 맺고 있는 필드를 설정해야 합니다.
Study 클래스 1 2 3 4 5 6 7 8 9 10 11 12 13 14 @Entity public class Study { @Id @GeneratedValue private Long id; private String name; @ManyToOne private Account owner; } `
Account를 종속시킨 주인 클래스로서 @ManyToOne을 선언합니다.
Account 클래스 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 @Entity public class Account { @Id @GeneratedValue private Long id; @Column (nullable = false , unique = true ) private String username; private String password; @OneToMany (mappedBy = "owner" ) private Set<Study> studies = new HashSet<>(); } `
mappedBy 를 통해서 종속관계를 설정해주어야 합니다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 @Component @Transactional public class JpaRunner implements ApplicationRunner { @PersistenceContext EntityManager entityManager; @Override public void run (ApplicationArguments args) throws Exception { Account account = new Account(); account.setUsername("kimjunhyeung" ); account.setPassword("1234" ); Study study = new Study(); study.setName("Spring Data JPA" ); account.getStudies().add(study); study.setOwner(account); Session session = entityManager.unwrap(Session.class); session.save(account); session.save(study); } }
주인 관계를 설정하는 로직의 작성은 필수이며 종속관계의 로직은 필수는 아닙니다. 그러나 객체지향적으로 활용하기 위해 주종 모두 관계를 설정 해주는 것이 좋습니다.
관계 설정 로직 1 2 account.getStudies().add(study); study.setOwner(account);
관계를 설정할 때 사용했던 로직입니다. 결과만 놓고 봤을 때는 주인쪽에 관계를 설정하면 이상 없지만 객체지향이기 때문에 양방향 관계를 설정해주어야합니다. 그래서 항상 같이 다니기 때문에 하나의 메소드로 묶어주면 편리합니다. 이 메소드를 컨비니언스(convinience) 메소드 라고 합니다.
addStudy 메소드 생성 1 2 3 4 public void addStudy (Study study) { this .getStudies().add(study); study.setOwner(this ); }
Account 클래스에서 Study를 추가할 때마다 관계를 설정하는 메소드를 생성합니다. 여기서 this는 account를 가르킵니다.
메소드 활용 1 account.addStudy(study);
애플리케이션 구동시 생성한 메소드만 호출해주면 관계 설정 로직이 구동됩니다.