
Pexels / Pixabay
こんにちは、mabuiです。
JPAでは推奨されていないみたいですが、サロゲートキーを使用しない、
ナチュラルキーのみの中間テーブルの作り方の紹介です。
テーブル定義
例えばwebサービスに良くあるような、お気に入りのページをストックする機能を作る場合、
お気に入り情報のエンティティを下記のようにテーブル定義します。
| 1 2 3 4 5 | create table favorite (     page_id bigint not null,     user_id bigint not null,     primary key (page_id, user_id) ) engine=InnoDB; | 
page_idとuser_idは多対多の関係性です。
お気に入り情報の追加と削除機能を実装する場合、
お気に入り削除時に、データ量削減のためレコードを削除するとします。
この時にサロゲートキーを使用していると、キーの値が飛び飛びになり、
なんか気持ち悪いです。
複合主キーの定義
そこで複合主キーの定義を行うわけですが、
JPAで主キーを指定する@id アノテーションは複合主キーでは使用できないため、
下記のようにエンティティクラスの実装を行います。
| 1 2 3 4 5 | @Embeddable data class FavoritePK(         val userId: Long,         val pageId: Long ): Serializable | 
| 1 2 3 4 5 6 | @Entity @Table(name = "favorite") data class Favorite(         @EmbeddedId         val favoritePK: FavoritePK ) | 
複合主キーにしたいフィールドをFavoritePKクラスとして、
@Embeddableを使って単一のフィールドにします。
Favoriteクラスには、FavoritePKのフィールドを@EmbeddedIdでid指定します。
これで、記事の最初に乗っけたテーブル定義にマッピングできます。
ちなみに、テーブルアクセス時にJPAのRepositoryインターフェースを使用する場合は、
FavoritePKのインスタンスを生成し、それを引数に使用します。
| 1 2 | val favorite = favoriteRepository.findOneByFavoritePK(FavoritePK(pageId, userId)) |