Spring JPA で複合主キーのテーブルのEntityを作成する方法を記載しています。
また、複合キーの中で一部のキーを用いてグループ化したEntityを作成する方法を紹介します。
※サンプルはKotlinとなっています。
1. 複合キーのEntity作成方法1
以下のような複合キーを持つテーブルのEntityを作成する場合
1-1. ID用のクラスを作成し、@Embeddable アノテーションを付与する。
1-2. 作成したIDクラスの型を持つIDカラムを作成し、@EmbeddedId アノテーションを付与する。
@Table(name = "transactions") @Entity open class Transactions : Serializable { @Embeddable open class Id : Serializable { @Column(name = "user_id", nullable = false) open var userId: Int? = null @Column(name = "product_id", nullable = false) open var productId: Int? = null @Column(name = "transaction_no", nullable = false) open var transactionNo: Int? = null } @EmbeddedId open var id: Id? = null @Column(name = "transaction_datetime") open var transactionDatetime: Date? = null }
ID 用のクラスを別に作成しても良いですが、inner class としておけば無駄なクラスを増やさずに済み、
型(Class)指定する際は以下のように全クラス共通して [Class name].Idでアクセスできるため、どのクラスのIDであるというのもわかりやすいです。
(例:Repositoryの定義)
interface TransactionsRepository : JpaRepository<Transactions, Transactions.Id> {
}
IDの値を利用した、別Entityとの関連を持たせたい場合
これにプラスして定義することもできます。
@Table(name = "transactions") @Entity open class Transactions : Serializable { @Embeddable open class Id : Serializable { @Column(name = "user_id", nullable = false) open var userId: Int? = null @Column(name = "product_id", nullable = false) open var productId: Int? = null @Column(name = "transaction_no", nullable = false) open var transactionNo: Int? = null } @EmbeddedId open var id: Id? = null @ManyToOne @JoinColumn(name = "user_id", nullable = false, insertable = false, updatable = false) open var user: Users? = null @ManyToOne @JoinColumn(name = "product_id", nullable = false, insertable = false, updatable = false) open var product: Products? = null @Column(name = "transaction_datetime") open var transactionDatetime: Date? = null }
2. 複合キーのEntity作成方法2
先ほどの@Embeddableを利用する方法の他に@IdClass アノテーションを利用する方法もあります。
2-1. ID(キー)用のクラスを作成する。
2-2. @IdClass アノテーションを付与し、作成したId用のクラスを指定する。
2-3. 各IDとなるプロパティに @Id アノテーションを付与する。
2-1
open class TransactionsKey : Serializable { open var userId: Int? = null open var productId: Int? = null open var transactionNo: Int? = null }
2-2, 2-3
@Table(name = "transactions") @Entity @IdClass(TransactionsKey::class) open class Transactions : Serializable { @Id @Column(name = "user_id", nullable = false) open var userId: Int? = null @Id @Column(name = "product_id", nullable = false) open var productId: Int? = null @Id @Column(name = "transaction_no", nullable = false) open var transactionNo: Int? = null @Column(name = "transaction_datetime") open var transactionDatetime: Date? = null }
(Repositoryでの指定)
interface MInspectionItemDeformationDisplayRepository : JpaRepository<MInspectionItemDeformationDisplay, TransactionsKey> {
}
3. 複合キーのテーブルで一部キーのみを除いたEntityの作成方法
複合主キーのテーブルにおいて、キーの一部のみでその他はグループ化した形で取得したい場合
(例で言うとユーザが商品ごとに行った取引の最新日時を持つEntityを作成する場合 等)
3-1. @Immutableアノテーションを付与
3-2. @Subselectにて取得したい内容を記載
※ここではHibernate のアノテーション (org.hibernate.annotations) @Subselectを使用しています。
@Entity @Immutable @Subselect(""" SELECT user_id, product_id, MAX(transaction_datetime) AS transaction_datetime FROM transactions GROUP BY user_id, product_id """) open class LatestTransactions { @Embeddable open class Id : Serializable { @Column(name = "user_id", nullable = false) open var userId: Int? = null @Column(name = "product_id", nullable = false) open var productId: Int? = null } @EmbeddedId open var id: Id? = null @Column(name = "transaction_datetime") open var transactionDatetime: Date? = null }