다양한 연관관계 매핑
- 엔티티의 연관관계를 매핑할 때는 3가지를 고려
- 다중성
다대일(@ManyToOne), 일대다(@OneToMany), 일대일(@OneToOne), 다대다(@ManyToMany) - 단방향, 양방향
테이블은 외래 키 하나로 조인을 사용해서 양방향으로 쿼리가 가능하므로 사실상 방향이라는 개념이 없음
반면에 객체는 참조용 필드를 가지고 있는 객체만 연관된 객체를 조회할 수 있음
객체 관계에서 한쪽만 참조하는 단방향 관계, 서로 참조하는 양방향 관계 - 연관관계의 주인
데이터베이스는 외래 키 하나로 두 테이블이 연관관계를 맺으므로 연관관계를 관리하는 포인트는 외래 키 하나
반면 객체는 엔티티를 양방향으로 매핑하면 2곳에서 서로를 참조하므로 객체의 연관관계를 관리하는 포인트는 둘
JPA는 두 객체 연관관계 중 하나를 정해서 데이터베이스 외래 키를 관리하는데 이것을 연관관계의 주인이라고 함
외래 키를 가진 테이블과 매핑한 엔티티가 외래 키를 관리하는 게 효율적이므로 보통 이곳을 연관관계의 주인으로 선택
주인이 아닌 방향은 외래 키를 변경할 수 없고 읽기만 가능
- 다중성과 단방향, 양방향을 고려한 가능한 모든 연관관계 (왼쪽을 연관관계의 주인으로 정함)
- 다대일 : 단방향, 양방향
- 일대다 : 단방향, 양방향
- 일대일 : 주 테이블 단방향, 양방향
- 일대일 : 대상 테이블 단방향, 양방향
- 다대다 : 단방향, 양방향
다대일
- 다대일 관계의 반대 방향은 항상 일대다 관계고 일대다 관계의 반대 방향은 항상 다대일 관계
- 데이터베이스 테이블의 일(1), 다(N) 관계에서 외래 키는 항상 다쪽에 있으므로
따라서 객체 양방향 관계에서 연관관계의 주인은 항상 다쪽
예) 회원(N)과 팀(1)이 있으면 회원 쪽이 연관관계의 주인 - 다대일 단방향 [N:1]
// 회원 엔티티
@Entity
public class Member {
@Id @GeneratedValue
@Column (name = "MEMBER_ID")
privaate Long id;
private String username;
@ManyToOne
/* Member.team 필드를 TEAM_ID 외래 키와 매핑
따라서 Member.team 필드로 회원 테이블의 TEAM_ID 외래 키를 관리 */
@JoinColumn (name = "TEAM_ID")
/* 회원은 Member.team으로 팀 엔티티를 참조할 수 있지만
반대로 팀에는 회원을 참고하는 필드가 없으므로
회원과 팀은 다대일 단방향 연관관계 */
private Team team;
// Getter, Setter ...
...
}
// 팀 엔티티
@Entity
public class Team {
@Id @GeneratedValue
@Column (name "TEAM_ID")
private Long id;
private String name;
// Getter, Setter ...
...
}
- 다대일 양방향 [N:1, 1:N]
실선이 연관관계의 주인(Member.team)이고 점선(Team.members)은 연관관계의 주인이 아님
// 회원 엔티티
@Entity
public class Member {
@Id @GeneratedValue
@Column (name = "MEMBER_ID")
privaate Long id;
private String username;
@ManyToOne
/* 일대다와 다대일 연관관계는 항상 다(N)에 외래 키가 있음
여기서 다쪽인 MEMBER 테이블이 외래 키를 가지고 있으므로
Member.team이 연관관계의 주인 */
@JoinColumn (name = "TEAM_ID")
private Team team;
/* 양방향 연관관계는 항상 서로를 참조해야 하므로 연관관계 편의 메소드를 작성
편의 메소드는 한 곳에만 작성하거나 양쪽 다 작성할 수 있는데,
양쪽에 다 작성하면 무한루프에 빠지므로 주의해야 하며
예제 코드는 편의 메소드를 양쪽에 다 작성해서 둘 중 하나만 호출하도록 하며
또한 무한루프에 빠지지 않도록 검사하는 로직이 존재 */
public void setTeam(Team team) {
this.team = team;
// 무한루프에 빠지지 않도록 체크
if(!team.getMembers().contains(this)) {
team.getMembers().add(this);
}
}
// Getter, Setter ...
...
}
// 팀 엔티티
@Entity
public class Team {
@Id @GeneratedValue
@Column (name "TEAM_ID")
private Long id;
private String name;
@OneToMany(mappedBy = "team")
private List<Member> members = new ArrayList<Member>();
public void addMember(Member member) {
this.members.add(member);
// 무한루프에 빠지지 않도록 체크
if(member.getTeam() != this) {
member.setTeam(this);
}
}
// Getter, Setter ...
...
}
일대다
- 일대다 관계는 엔티티를 하나 이상 참조할 수 있으므로 자바 컬렉션인 Collection, List, Set, Map 중에 하나를 사용해야 함
- 일대다 단방향 [1:N]
예) 하나의 팀은 여러 회원을 참조할 수 있으며, 반대로 회원은 팀을 참조하지 않으면 둘의 관계는 단방향
// 팀 엔티티
@Entity
public class Team {
@Id @GeneratedValue
@Column (name = "TEAM_ID")
private Long id;
private String name;
@OneToMany // 일대다 단방향 관계
/* 팀 엔티티의 Team.members로 회원 테이블의 TEAM_ID 외래 키를 관리
즉, 자신이 매핑한 테이블의 외래 키를 관리하는 것이 아닌,
반대쪽 테이블에 있는 외래 키를 관리하는 매핑
Member 엔티티에는 외래 키를 매핑할 수 있는 참조 필드가 없지만,
반대쪽인 Team 엔티티에만 참조 필드인 members가 있으므로
반대편 테이블의 외래 키를 관리하는 특이한 모습 */
@JoinColumn (name = "TEAM_ID") // MEMBER 테이블의 TEAM_ID (FK)
private List<Member> members = new ArrayList<Member>();
// Getter, Setter ...
}
// 회원 엔티티
@Entity
public class Member {
@Id @GeneratedValue
@Column (name = "MEMBER_ID")
private Long id;
private String username;
// Getter, Setter ...
}
일대다 단방향 매핑은 매핑한 객체가 관리하는 외래 키가 다른 테이블에 있다는 단점이 존재
그러므로 본인 테이블에 외래 키가 있으면 엔티티의 저장과 연관관계 처리를 INSERT SQL 한 번으로 끝낼 수 있지만,
다른 테이블에 외래 키가 있으면 연관관계 처리를 위한 UPDATE SQL을 추가로 실행해야 함
즉, Team 엔티티를 저장할 때 Team.members의 참조 값을 확인하여 회원 테이블에 있는 TEAM_ID 외래 키를 업데이트
public void testSave() {
Member member1 = new Member("member1");
Member member2 = new Member("member2");
Team team1 = new Team("team1");
team1.getMembers().add(member1);
team1.getMembers().add(member2);
em.persist(member1); // INSERT-member1
em.persist(member2); // INSERT-member2
em.persist(team1); // INSERT-team1, UPDATE-member1.fk, UPDATE-member2.fk
transaction.commit();
}
// 위를 실행한 결과 SQL
// 회원 엔티티는 팀 엔티티를 모르므로 연관관계에 대한 정보는 Team 엔티티의 members가 관리
// 따라서 Member 엔티티를 저장할 때는 MEMBER 테이블의 TEAM_ID 외래 키에 아무 값도 저장되지 않음
// 대신 Team 엔티티를 저장할 때 Team.members의 참조 값을 확인하여 회원 테이블에 있는 TEAM_ID 외래 키를 업데이트
insert into Member (MEBMER_ID, username) values (null, ?)
insert into Member (MEBMER_ID, username) values (null, ?)
insert into Team (TEAM_ID, name) values (null, ?)
update Member set TEAM_ID=? where MEMBER_ID=?
update Member set TEAM_ID=? where MEMBER_ID=?
일대다 단방향 매핑을 사용하면 엔티티를 매핑한 테이블이 아닌 다른 테이블의 외래 키를 관리해야 함
성능 문제와 더불어 관리가 부담스러우므로 일대다 단방향 매핑보다는 다대일 양방향 매핑을 사용하자
다대일 양방향 매핑의 경우 외래 키가 본인 테이블에 있고 두 매핑의 테이블 모양이 완전히 같으므로 다대일 양방향 매핑을 권장
- 양방향 [1:N, N:1]
일대다 양방향 매핑은 존재하지 않으므로 대신 다대일 양방향 매핑을 사용
또한 관계형 데이터베이스의 특성상 일대다, 다대일 관계는 항상 다 쪽에 외래 키가 있으므로
@OneToMany는 연관관계의 주인이 될 수 없으며 이러한 이유로 @ManyToOne에는 mappedBy 속성이 존재하지 않음
그렇지만 일대다 양방향 매핑이 완전히 불가능한 것은 아니며,
일대다 단방향 매핑 반대편에 외래 키를 사용하는 다대일 단방향 매핑을 읽기 전용으로 하나 추가하면 됨
하지만 이 방법은 일대다 양방향 매핑이라기보다는 일대다 단방향 매핑 반대편에 다대일 단방향 매핑을 읽기 전용으로
추가해 일대다 양방향처럼 보이도록 하므로 일대다 단방향 매핑이 가지는 단점을 그대로 가지므로 다대일 양방향 매핑 권장
// 팀 엔티티
@Entity
public class Team {
@Id @GeneratedValue
@Column (name = "TEAM_ID")
private Long id;
private String name;
@OneToMany // 일대다 단방향 관계
@JoinColumn (name = "TEAM_ID")
private List<Member> members = new ArrayList<Member>();
// Getter, Setter ...
}
// 회원 엔티티
@Entity
public class Member {
@Id @GeneratedValue
@Column (name = "MEMBER_ID")
private Long id;
private String username;
@ManyToOne // 다대일 단방향 매핑 (일대다 단방향 매핑 반대편에 추가)
/* TEAM_ID 외래 키 컬럼을 매핑했으며,
이렇게 두 엔티티가 같은 키를 관리하면 문제가 발생할 수 있으므로
다대일 쪽은 insertable = false, updatable = false로 설정해서 읽기만 가능하도록 함 */
@JoinColum (name = "TEAM_ID", insertable = false, updatable = false)
private Team team;
// Getter, Setter ...
}
일대일 [1:1]
- 일대일 관계는 양쪽이 서로 하나의 관계만 가짐
예) 회원은 하나의 사물함만 사용, 사물함도 하나의 회원에 의해서만 사용됨 - 일대일 관계의 특징
- 일대일 관계는 그 반대로 일대일 관계
- 테이블 관계에서 일대다, 다대일은 항상 다쪽이 외래 키를 가지는 반면, 일대일 관계는 어느 곳이나 외래 키를 가질 수 있음
그러므로 테이블은 주 테이블이든 대상 테이블이든 외래 키 하나만 있으면 양쪽으로 조회 가능
- 주 테이블에 외래 키 - 객체지향 개발자들이 선호
주 객체가 대상 객체를 참조하는 것처럼 주 테이블에 외래 키를 두고 대상 테이블을 참조
주 테이블이 외래 키를 가지고 있으므로 주 테이블만 확인해도 대상 테이블과 연관관계가 있는지 알 수 있음
- 단방향
@Entity
public class Member { // 주 테이블
@Id @GeneratedValue
@Column (name = "MEMBER_ID")
private Long id;
private String username;
@OneToOne // 일대일 단방향 관계
@JoinColumn (name "LOCKER_ID") // 외래 키
private Locker locker;
...
}
@Entity
public class Locker { // 대상 테이블
@Id @GeneratedValue
@Column (name = "LOCKER_ID")
private Long id;
private String name;
...
}
-
- 양방향
@Entity
public class Member { // 주 테이블
@Id @GeneratedValue
@Column (name = "MEMBER_ID")
private Long id;
private String username;
@OneToOne // 일대일 양방향 관계
@JoinColumn (name "LOCKER_ID") // 외래 키를 가지므로 Member.locker가 연관관계의 주인
private Locker locker;
...
}
@Entity
public class Locker { // 대상 테이블
@Id @GeneratedValue
@Column (name = "LOCKER_ID")
private Long id;
private String name;
@OneToOne(mappedBy = "locker") // 일대일 양방향 관계, 연관관계의 주인이 아님
private Member member;
...
}
- 대상 테이블에 외래 키 - 데이터베이스 개발자들이 선호
대상 테이블에 외래 키를 두는 것으로 테이블 관계를 일대일에서 일대다로 변경할 때 테이블 구조를 그대로 유지할 수 있는 장점
- 단방향
일대일 단방향에서 대상 테이블에 외래 키가 있는 경우 JPA가 지원하지 않으며,
이때는 단방향 관계를 Locker에서 Member 방향으로 수정하거나,
양방향 관계로 만들고 Locker를 연관관계의 주인으로 설정해야 함 - 양방향
- 단방향
@Entity
public class Member { // 주 테이블
@Id @GeneratedValue
@Column (name = "MEMBER_ID")
private Long id;
private String username;
@OneToOne(mappedBy = "member") // 일대일 양방향 관계, 연관관계의 주인이 아님
private Locker locker;
...
}
@Entity
public class Locker { // 대상 테이블
@Id @GeneratedValue
@Column (name = "LOCKER_ID")
private Long id;
private String name;
@OneToOne // 일대일 양방향 관계, 연관관계의 주인
@JoinColumn (name = "MEMBER_ID")
private Member member;
...
}
다대다 [N:N]
- 관계형 데이터베이스는 정규화된 테이블 2개로 다대다 관계를 표현할 수 없으므로
보통 다대다 관계를 일대다, 다대일 관계로 풀어내는 연결 테이블을 사용
예) 회원과 상품이 있을 때 다대다 관계이지만 두 테이블만으로는 관계를 표현할 수 없으므로 중간 연결인 주문 상품 테이블 추가
반면 객체는 테이블과 다르게 컬렉션을 사용해 객체 2개로 다대다 관계를 만들 수 있으므로 @ManyToMany를 사용 - 단방향
@Entity
public class Member { // 회원
@Id @Column (name = "MEMBER_ID")
private String id;
private string username;
@ManyToMany // 다대다 단방향
/* @ManyToMany와 @JoinTable을 사용해서 연결 테이블을 바로 매핑하며
다대다 관계를 일대다, 다대일 관계로 풀어내기 위해 필요한 연결 테이블인
회원과 상품을 연결하는 Member_product 엔티티 (생성) 없이 매핑을 완료 */
@JoinTable(name = "MEMBER_PRODUCT", // 연결 테이블을 지정
joinColumns = @JoinColumn (name = "MEMBER_ID"), // 현재 방향인 회원과 매핑할 조인 컬럼 정보 지정
inverseJoinColumns = @JoinColumn (name = "PRODUCT_ID")) // 반대 방향인 상품과 매핑할 조인 컬럼 정보 지정
private List<Product> products = new ArrayList<Product>();
...
}
@Entity
public class Product { // 상품
@Id @Column (name "PRODUCT_ID")
private String id;
private String name;
...
}
// 다대다 관계 저장
public void save() {
Product productA = new Product();
productA.setId("productA");
productA.setName("상품A");
em.persist(productA);
Member member1 = new Member();
member1.setId("member1");
member1.setUsername("회원1");
member1.getProducts().add(productA); // 회원1과 상품A의 연관관계 설정
em.persist(member1); // 회원1을 저장할 때 연결 테이블(MEMBER_PRODUCT)에도 값이 저장됨
}
// 위의 코드로 실행되는 SQL
INSERT INTO PRODUCT ...
INSERT INTO MEMBER ...
INSERT INTO MEMBER_PRODUCT ...
// 다대다 관계 탐색
public void find() {
Member member = em.find(Member.class, "member1");
List<Product> products = member.getProducts(); // 객체 그래프 탐색
for (Product product : products) { // 저장해두었던 상품1이 조회
System.out.println("product.name = " + product.getName());
}
}
// 위의 코드로 실행되는 SQL
SELECT * FROM MEMBER_PRODUCT MP
// 연결 테이블인 MEMBER_PRODUCT와 상품 테이블을 조인해서 연관된 상품을 조회
INNER JOIN PRODUCT P ON MP.PRODUCT_ID=P.PRODUCT_ID
WHERE MP.MEMBER_ID=?
- 양방향
역방향도 @ManyToMany를 사용한 후 양쪽 중 원하는 곳에 mappedBy로 연관관계의 주인 지정
@Entity
public class Member { // 회원
@Id @Column (name = "MEMBER_ID")
private String id;
private string username;
@ManyToMany // 다대다 양방향, 연관관계의 주인
@JoinTable(name = "MEMBER_PRODUCT", // 연결 테이블을 지정
joinColumns = @JoinColumn (name = "MEMBER_ID"),
inverseJoinColumns = @JoinColumn (name = "PRODUCT_ID"))
private List<Product> products = new ArrayList<Product>();
...
public void addProduct(Product product) { // 양방향 연관관계 설정 편의 메소드
...
products.add(product); // == member.getProducts().add(product)
product.getMembers().add(this); == product.getMembers().add(member)
}
}
@Entity
public class Product { // 상품
@Id @Column (name "PRODUCT_ID")
private String id;
@ManyToMany (mappedBy = "products") // 다대다 양방향 - 역방향 추가, 연관관계의 주인이 아님
private String name;
...
}
// 양방향 연관관계로 만들었으므로 역방향으로 객체 그래프 탐색
public void findInverse() {
Product product = em.find(Product.class, "productA");
List<Member> members = product.getMembers();
for (Member member : members) {
System.out.println("member = " + member.getUsername());
}
}
- 매핑의 한계와 극복, 연결 엔티티 사용 (식별 관계)
@ManyToMany를 사용하면 연결 테이블을 자동으로 처리해주므로 도메인 모델이 단순해지고 여러 가지로 편리하지만,
이 매핑을 실무에서 사용하기에는 한계가 있음
예) 회원이 상품을 주문하면 연결 테이블에 단순히 주문한 회원의 아이디와 상품 아이디만 담고 끝나지 않으며,
주문 수량 컬럼, 주문한 날짜 컬럼 등이 더 필요 위와 같이 주문 수량과 주문 날짜 컬럼을 추가하면 추가한 컬럼들을 매핑할 수 없으므로 더는 @ManyToMany를 사용할 수 없음
그러므로 결국 연결 테이블을 매핑하는 연결 테이블을 만들고 이곳에 추가한 컬럼들을 매핑해야 함
그 후 엔티티 간의 관계도 테이블 관계처럼 다대다에서 일대다, 다대일 관계로 풀어야 함
// 회원 엔티티
@Entity
public class Member {
@Id @Column (name = "MEMBER_ID")
private Long id;
// 역방향
@OneToMany(mappedBy = "member") // 회원과 회원 상품은 양방향 관계, 연관관계의 주인이 아님
private List<MemberProduct> memberProducts;
...
}
// 상품 엔티티
@Entity
public class Product {
@Id @Column (name "PRODUCT_ID")
private String id;
// 상품 엔티티에서 회원상품 엔티티로 객체 그래프 탐색 기능이 필요하지 않다고 판단해
// 연관관계를 만들지 않음
private String name;
...
}
// 회원상품 엔티티
/* 기본 키를 매핑하는 @Id와 외래 키를 매핑하는 @JoinColumn을 동시에 사용해 기본 키 + 외래 키를 한번에 매핑
기본 키가 MEMBER_ID와 PRODUCT_ID로 이루어진 복합 기본 키이므로 별도의 식별자 클래스 필요
@IdClass를 사용해서 복합 기본 키를 매핑 */
@Entity
@IdClass(MemberProductId.class) // 식별자 클래스 지정
public class MemberProduct {
/* 회원 상품은 회원과 상품의 기본 키를 받아서 자신의 키로 사용하는데
이렇게 부모 테이블의 기본 키를 받아서 자신의 기본 키 + 외래 키로 사용하는 것을
데이터베이스 용어로 식별 관계라고 칭함 */
@Id
@ManyToOne // 회원과 회원 상품은 양방향 관계, 연관관계의 주인
@JoinColumn (name = "MEMBER_ID")
private Member member; // MemberProductId.member와 연결
@Id
@ManyToOne
@JoinColumn (name = "PRODUCT_ID")
private Product product; // MemberProductId.product와 연결
private int orderAmount;
...
}
// 회원상품 식별자 클래스
// 기본 키가 MEMBER_ID와 PRODUCT_ID로 이루어진 복합 기본 키이므로 별도의 식별자 클래스 필요
/* 복합 키를 위한 별도의 식별자 클래스
1. 복합 키는 별도의 식별자 클래스로 만들어야 함
2. Serializable을 구현해야 하며, equals와 hashCode 메소드를 구현해야 함
3. 기본 생성자가 있어야 함
4. 식별자 클래스는 public
5. @IdClass를 사용하는 방법 외에 @EmbeddedId를 사용하는 방법도 존재 */
public class MemberProductId implements Serializable {
private String member; // MemberProduct.member와 연결
private String product; // MemberProduct.product와 연결
// hashCode and equals
@Override
public boolean equals(Object o) { ... }
@Override
public int hashCode() { ... }
}
// 저장하는 코드
public void save() {
// 회원 저장
Member member1 = new Member();
member1.setId("member1");
member1.setUsername("회원1");
em.persist(member1);
// 상품 저장
Product product1 = new Product();
product1.setId("productA");
product1.setName("상품1");
em.persist(productA);
// 회원상품 저장
// 데이터베이스에 저장될 때 연관된 회원의 식별자와 상품의 식별자를 가져와서 자신의 기본 키 값으로 사용
MemberProduct memberProduct = new MemberProduct();
memberProduct.setMember(member1); // 주문 회원 - 연관관계 설정
memberProduct.setProduct(productA); // 주문 상품 - 연관관계 설정
memberProduct.setOrderAmount(2); // 주문 수량
em.persist(memberProduct);
}
// 조회 코드
public void find() {
// 기본 키 값 설정
// 복합 키는 항상 식별자 클래스를 만든 후, 생성한 식별자 클래스로 엔티티를 조회
MemberProductId memberProductId = new MemberProductId();
memberProductId.setMember("member1");
memberProductId.setProduct("productA");
// 식별자 클래스로 엔티티 조회
MemberProduct memberProduct = em.find(MemberProduct.class, memberProductId);
Member member = memberProduct.getMember();
Product product = memberProduct.getProduct();
System.out.println("member = " + member.getUsername());
System.out.println("product = " + product.getName());
System.out.println("orderAmount = " + memberProduct.getOrderAmount());
}
- 새로운 기본 키 사용 (비식별 관계)
복합 키를 사용하지 않고 다대다 관계를 구성하는 방법으로 데이터베이스에서 자동으로 생성해주는 대리 키를 Long 값으로 사용
간편하고 영구히 쓸 수 있으며 비즈니스에 의존하지 않으며, ORM 매핑 시에 복합 키를 만들지 않고 간단히 매핑 완료 가능
연결 테이블에 새로운 기본 키를 사용해 주문이라는 이름으로 연결 테이블 생성
// 주문 엔티티
@Entity
public class Order {
@Id @GenereatedValue
@Column (name = "ORDER_ID") // 새로운 기본 키 생성
private Long Id;
@ManyToOne
@JoinColumn (name = "MEMBER_ID") // 외래 키로만 사용 (기본 키로 사용 X)
private Member member;
@ManyToOne
@JoinColumn (name = "PRODUCT_ID") // 외래 키로만 사용 (기본 키로 사용 X)
private Product product;
private int orderAmount;
...
}
@Entity
public class Member { // 회원
@Id @Column (name = "MEMBER_ID")
private String id;
private string username;
@OneToMany(mappedBy="member")
private List<Order> orders = new ArrayList<Order>();
...
}
@Entity
public class Product { // 상품
@Id @Column (name "PRODUCT_ID")
private String id;
private String name;
...
}
// 저장하는 코드
public void save() {
// 회원 저장
Member member1 = new Member();
member1.setId("member1");
member1.setUsername("회원1");
em.persist(member1);
// 상품 저장
Product product1 = new Product();
product1.setId("productA");
product1.setName("상품1");
em.persist(productA);
// 주문 저장
Order order = new Order();
order.setMember(member1); // 주문 회원 - 연관관계 설정
order.setProduct(productA); // 주문 상품 - 연관관계 설정
order.setOrderAmount(2); // 주문 수량
em.persist(order);
}
// 조회 코드
public void find() {
Long orderId = 1L;
Order order = em.find(Order.class, orderId);
Member member = order.getMember();
Product product = order.getProduct();
System.out.println("member = " + member.getUsername());
System.out.println("product = " + product.getName());
System.out.println("orderAmount = " + order.getOrderAmount());
}
- 다대다 연관관계 정리
다대다 관계를 일대다 다대일 관계로 풀어내기 위해 연결 테이블을 만들 때 식별자를 어떻게 구성할지 선택해야 함
1) 식별 관계 : 받아온 식별자를 기본 키 + 외래 키로 사용
2) 비식별 관계 : 받아온 식별자는 외래 키로만 사용하고 새로운 식별자를 추가
비식별 관계를 사용하면 복합 키를 위한 식별자 클래스를 만들지 않아도 되므로 단순하고 편리하게 ORM 매핑을 할 수 있어 추천
'Java-Spring > 자바 ORM 표준 JPA 프로그래밍' 카테고리의 다른 글
[자바 ORM 표준 JPA 프로그래밍] 고급 매핑 (0) | 2022.04.12 |
---|---|
[자바 ORM 표준 JPA 프로그래밍] 다양한 연관관계 매핑 - 실전 예제 (0) | 2022.04.04 |
[자바 ORM 표준 JPA 프로그래밍] 연관관계 매핑 기초 - 실전 예제 (0) | 2022.03.31 |
[자바 ORM 표준 JPA 프로그래밍] 연관관계 매핑 기초 (0) | 2022.03.29 |
[자바 ORM 표준 JPA 프로그래밍] 엔티티 매핑 - 실전 예제 (0) | 2022.03.26 |