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
}