Spring Data JPAで複数テーブルからQueryを書かずにいい感じで情報を集めて1つの情報にする

f:id:akagoma:20211121114728p:plain

はじめに

Springbootを使っているアプリケーション、かつSpring Data JPAを採用しているアプリケーションにおいて、「複数のテーブルからデータを取得して1つの情報クラスとしたい」場合がある。

もちろん複数のテーブルそれぞれにアクセスして、情報を取得して1つの情報クラスにセットすれば良いのだが、これは個人的にスマートなやり方とは言えない。SQLデータベースなのだから、自由に情報を結合することはできるはずだからだ。

「spring data jpa 複数テーブル」で検索しても、@Repositoryを付与してせっかくクエリ文を書く手間を省いている@Repositoryインターフェースに、自分で@Queryを付与してクエリ文を書いているものや、データの型がそのままテーブルのEntityクラスになっているもの(下図)しか出てこなかった。

f:id:akagoma:20211119164108p:plain

確かにこれでも実現できるが、クエリ文も書かずに楽して1つの情報クラスとしたい。

f:id:akagoma:20211119164207p:plain

クエリ文も書かずに、いい感じにする方法

下準備

まずはAccountEntityとAuthenticationEntityのクラスを作成し、リポジトリも作成する。

※idが数値(Long)なのには理由があり、@Queryを利用して、うまいことインクリメント処理が書けるのかどうかを検証するためにLongになっている。このインクリメント処理も後日ブログに掲載する予定。

いい感じにする

いい感じにする答えは@SecondaryTableを利用することだった。

軸とするリポジトリのEntityをベースに@SecondaryTableと@Columnアノテーションを使い、一部の情報を別テーブルから取得することができる。

もし、このクラスを使って複数テーブルにレコードの追加/更新をする場合はupdatableとinsertableをtrueにすればよい。逆に情報取得だけの場合はfalseにしておくのが無難。

感想

「クエリ文を書くのが嫌い」ということを発端に調査した内容だったが、ドンピシャなことが実現できてよかった。

確かにEntityの中にEntityクラスを変数として持たせれば解決はする。しかし、内側の情報にたどり着くためにEntityA.getEntityB().getXXX()とするのが面倒くさい(というか読みにくかったので)この方法が一番しっくりきた。

欠点としては、テーブルの構成をしっかり理解していないと、このAccountInfoクラスのテーブルが存在していると勘違いされる可能性がある。

 

SQLの勉強として、インプレス社の本はSQL初心者にとって読みやすかった。

※読んだ上で、「クエリ文は自動生成が最高だな」と思い今に至っている。

 

Copyright (C) 2021 akagoma. All Rights Reserved.