emiling / TIL

RAM → SSD
1 stars 0 forks source link

JPA 고급 매핑 #11

Open emiling opened 2 years ago

emiling commented 2 years ago

JPA 고급 매핑

출처 : 자바 ORM 표준 JPA 프로그래밍 7장 JPA 시작(김영한 저)

emiling commented 2 years ago

상속관계 매핑

조인전략

예시

// 상품 (부모 클래스)
@Entity
@Inheritence(strategy = Inheritance.JOINED)
@DiscriminatorColumn(name = "DTYPE")
abstract class Product(
    @Id @GeneratedValue
    @Column(name = "product_id")
    val id: Long,
    val name: String? = null,
    val price: Int? = null
)

// 앨범 (자식 클래스)
@Entity
@DiscriminatorValue("A")
class Album(
    val artist: String?
): Product

// 영화 (자식 클래스)
@Entity
@DiscriminatorValue("M")
class Movie(
    val director: String?
    val actor: String?
): Product

// 책 (자식 클래스)
@Entity
@DiscriminatorValue("B")
@PrimaryKeyValueJoinColumn(name = "book_id")
class Book(
    val author: String?
    val isbn: String?
): Product

장단점

단일 테이블 전략

예시

// 상품 (부모 클래스)
@Entity
@Inheritence(strategy = Inheritance.SINGLE_TABLE)
@DiscriminatorColumn(name = "DTYPE")
abstract class Product(
    @Id @GeneratedValue
    @Column(name = "product_id")
    val id: Long,
    val name: String? = null,
    val price: Int? = null
)

// 앨범 (자식 클래스)
// ... 위와 동일

// 영화 (자식 클래스)
// ... 위와 동일

// 책 (자식 클래스)
// ... 위와 동일

장단점

구현 클래스마다 테이블 전략

예시

@Entity
@Inheritence(strategy = Inheritance.TABLE_PER_CLASS)
abstract class Product(
    @Id @GeneratedValue
    @Column(name = "product_id")
    val id: Long,
    val name: String? = null,
    val price: Int? = null
)

// 앨범 (자식 클래스)
// ... 위와 동일

// 영화 (자식 클래스)
// ... 위와 동일

// 책 (자식 클래스)
// ... 위와 동일

장단점

@MappedSuperClass

emiling commented 2 years ago

상속관계 매핑 (2)

부모 클래스 매핑 하지 않는 경우

예시

@MappedSuperclass
class BaseEntity(
    @Id
    @GeneratedValue
    var id: Long = 0,
    val name: String? = null
)

@Entity
data class User(
    val email: String?
): BaseEntity()

@Entity
data class Seller(
    val shopName: String?
): BaseEntity()
emiling commented 2 years ago

복합키와 식별관계 매핑

식별관계 VS 비식별관계

복합키

복합키 : 비식별 관계 매핑

IdClass 사용


@Entity
@IdClass(ParentId::class)
data class Parent(
    @Id
    @Column("parent_id1")
    val id1: String,
    @Id
    @Column("parent_id2")
    val id2: String,
    @Column("name")
    val name: String
)

data class ParentId(
    val id1: String,
    val id2: String
) : Serializable

@Entity
data class Child(
    @Id
    val id: String,
    @ManyToOne
    @JoinColumns(
        // 이렇게 두 컬럼이 동일하면 referencedColumnName 생략 가능
        JoinColumn(name = "parent_id1", referencedColumnName = "parent_id1"), 
        JoinColumn(name = "parent_id2", referencedColumnName = "parent_id2")
    )
    val parent: Parent? = null
)

EmbeddedId 사용

@Entity
data class Parent(
    @EmbeddedId
    val id: ParentId,
    @Column(name = "name")
    val name: String
)

@Embeddable
data class ParentId(
    @Column(name = "parent_id1")
    val id1: String,
    @Column(name = "parent_id2")
    val id2: String
) : Serializable

복합키 : 식별 관계 매핑

IdClass 사용

@Entity
data class Parent(
    @Id @Column(name = "parent_id")
    val id: String
)

@Entity
@IdClass(ChildId::class)
data class Child(
    @Id
    @ManyToOne
    @JoinColumn(name = "parent_id")
    val parent: Parent,
    @Id @Column(name = "child_id")
    val childId: String,
)

data class ChildId(
    val parent: String, // Child.parent 매핑
    val childId: String // Child.childId 매핑
) : Serializable

@Entity
@IdClass(GrandChildId::class)
data class GrandChild(
    @Id
    @ManyToOne
    @JoinColumns(
        JoinColumn(name = "parent_id"),
        JoinColumn(name = "child_id"),
    )
    val child: Child,
    @Id @Column(name = "grandchild_id")
    val id: String,

)

@Embeddable
data class GrandChildId(
    val child: ChildId, // GrandChild.child 매핑
    val id: String // GrandChild.id 매핑
) : Serializable

EmbeddedId 사용

@Entity
data class Parent(
    @Id @Column(name = "parent_id")
    val id: String
)

@Entity
data class Child(
    @MapsId("parentId")
    @ManyToOne
    @JoinColumn(name = "parent_id")
    val parent: Parent,

    @EmbeddedId
    val childId: ChildId,
)

@Embeddable
data class ChildId(
    val parentId: String,
    @Column(name = "child_id")
    val id: String
) : Serializable

@Entity
data class GrandChild(
    @MapsId("childId")
    @ManyToOne
    @JoinColumns(
        JoinColumn(name = "parent_id"),
        JoinColumn(name = "child_id"),
    )
    val child: Child,

    @EmbeddedId
    val id: GrandChildId,

)

@Embeddable
data class GrandChildId(
    val childId: ChildId,
    @Column(name = "grandchild_id")
    val id: String
) : Serializable

비식별 관계로 구현

@Entity
data class Parent(
    @Id @GeneratedValue
    @Column(name = "parent_id")
    val id: Long
)

@Entity
data class Child(
    @Id @GeneratedValue
    @Column(name = "parent_id")
    val id: Long,
    val name: String,
    @ManyToOne
    @JoinColumn(name = "parent_id")
    val parent: Parent
)

@Entity
data class GrandChild(
    @Id @GeneratedValue
    @Column(name = "parent_id")
    val id: Long,
    @ManyToOne
    @JoinColumn(name = "child_id")
    val child: Child
)

일대일 식별 관계

@Entity
data class Board(
    @Id @GeneratedValue
    @Column(name = "board_id")
    val id: Long,
    val title: String,
    @OneToOne(mappedBy = "board")
    val boardDetail: BoardDetail
)

@Entity
data class BoardDetail(
    @Id
    val boardId: Long,
    @MapsId // BoardDetail.boardId 매핑
    @OneToOne
    @JoinColumn(name = "board_id")
    val board: Board,
    val content: String?
)