Spring DataJPAと名前付きエンティティグラフ

1。概要

簡単に言うと、エンティティグラフはJPA2.1でクエリを記述するもう1つの方法です。それらを使用して、よりパフォーマンスの高いクエリを作成できます。

このチュートリアルでは、簡単な例を使用して、Spring DataJPAを使用してエンティティグラフを実装する方法を学習します。

2.エンティティ

まず、複数の特性を持つItemというモデルを作成しましょう。

@Entity public class Item { @Id private Long id; private String name; @OneToMany(mappedBy = "item") private List characteristics = new ArrayList(); // getters and setters }

それでは、Cの特徴的なエンティティを定義しましょう。

@Entity public class Characteristic { @Id private Long id; private String type; @ManyToOne(fetch = FetchType.LAZY) @JoinColumn private Item item; //Getters and Setters }

コードでわかるように、Itemエンティティの特性フィールドとCharacteristicエンティティのitemフィールドの両方が、fetchパラメータを使用して遅延ロードされます。したがって、ここでの目標は、実行時にそれらを熱心にロードすることです。

3.エンティティグラフ

春データJPAでは、我々は、使用してエンティティのグラフを定義することができるの組み合わせ@NamedEntityGraph@EntityGraph注釈を。または、@ EntityGraphアノテーションのattributePaths引数のみを使用してアドホックエンティティグラフを定義することもできます

それがどのように行われるか見てみましょう。

3.1。@NamedEntityGraph

まず、JPAの@NamedEntityGraphアノテーションをItemエンティティで直接使用できます。

@Entity @NamedEntityGraph(name = "Item.characteristics", attributeNodes = @NamedAttributeNode("characteristics") ) public class Item { //... }

次に、@ EntityGraphアノテーションをリポジトリメソッドの1つにアタッチできます。

public interface ItemRepository extends JpaRepository { @EntityGraph(value = "Item.characteristics") Item findByName(String name); }

コードが示すように、我々は、エンティティグラフの名前渡されてきた私たちは、以前に作成したアイテム・エンティティ、@EntityGraphの注釈を。メソッドを呼び出すとき、それはSpringDataが使用するクエリです。

@EntityGraphアノテーションのtype引数のデフォルト値は、EntityGraphType.FETCHです。これを使用すると、SpringDataモジュールは指定された属性ノードにFetchType.EAGER戦略を適用します。また、その他の場合は、FetchType.LAZY戦略が適用されます。

したがって、この場合、@ OneToManyアノテーションのデフォルトのフェッチ戦略が怠惰であっても、特性プロパティは熱心にロードされます。

ここでの1つの落とし穴、定義されたフェッチ戦略がEAGERの場合、その動作をLAZYに変更できないことです。後続の操作では、実行後の時点で熱心にフェッチされたデータが必要になる可能性があるため、これは仕様によるものです。

3.2。@NamedEntityGraphなし

それとも、私たちは、あまりにも、アドホックエンティティグラフを定義することができattributePaths。

Itemの親を熱心にロードするAd-hocエンティティグラフをCharacteristicsRepositoryに追加しましょう。

public interface CharacteristicsRepository extends JpaRepository { @EntityGraph(attributePaths = {"item"}) Characteristic findByType(String type); }

これにより、エンティティがこのプロパティの遅延読み込み戦略を宣言している場合でもCharacteristicエンティティのitemプロパティが熱心に読み込まれます。

これは、既存の名前付きエンティティグラフを参照する代わりに、エンティティグラフをインラインで定義できるので便利です。

4.テストケース

エンティティグラフを定義したので、それを検証するためのテストケースを作成しましょう。

@DataJpaTest @RunWith(SpringRunner.class) @Sql(scripts = "/entitygraph-data.sql") public class EntityGraphIntegrationTest { @Autowired private ItemRepository itemRepo; @Autowired private CharacteristicsRepository characteristicsRepo; @Test public void givenEntityGraph_whenCalled_shouldRetrunDefinedFields() { Item item = itemRepo.findByName("Table"); assertThat(item.getId()).isEqualTo(1L); } @Test public void givenAdhocEntityGraph_whenCalled_shouldRetrunDefinedFields() { Characteristic characteristic = characteristicsRepo.findByType("Rigid"); assertThat(characteristic.getId()).isEqualTo(1L); } }

最初のテストでは、@ NamedEntityGraphアノテーションを使用して定義されたエンティティグラフを使用します。

Hibernateによって生成されたSQLを見てみましょう。

select item0_.id as id1_10_0_, characteri1_.id as id1_4_1_, item0_.name as name2_10_0_, characteri1_.item_id as item_id3_4_1_, characteri1_.type as type2_4_1_, characteri1_.item_id as item_id3_4_0__, characteri1_.id as id1_4_0__ from item item0_ left outer join characteristic characteri1_ on item0_.id=characteri1_.item_id where item0_.name=?

比較のために、リポジトリから@EntityGraphアノテーションを削除し、クエリを調べてみましょう。

select item0_.id as id1_10_, item0_.name as name2_10_ from item item0_ where item0_.name=?

これらのクエリから、@ EntityGraphアノテーションなしで生成されたクエリCharacteristicエンティティのプロパティをロードしていないことがはっきりとわかりますその結果、Itemエンティティのみがロードされます。

最後に、2番目のテストのHibernateクエリを@EntityGraphアノテーションと比較してみましょう。

select characteri0_.id as id1_4_0_, item1_.id as id1_10_1_, characteri0_.item_id as item_id3_4_0_, characteri0_.type as type2_4_0_, item1_.name as name2_10_1_ from characteristic characteri0_ left outer join item item1_ on characteri0_.item_id=item1_.id where characteri0_.type=?

そして、@ EntityGraphアノテーションのないクエリ:

select characteri0_.id as id1_4_, characteri0_.item_id as item_id3_4_, characteri0_.type as type2_4_ from characteristic characteri0_ where characteri0_.type=?

5。結論

このチュートリアルでは、SpringDataでJPAエンティティグラフを使用する方法を学習しました。Spring Dataを使用すると、さまざまなエンティティグラフにリンクされた複数のリポジトリメソッドを作成できます

この記事の例は、GitHubで入手できます。