Spring Data Java 8のサポート

Spring Data Java 8のサポート

1. 概要

Spring Dataは、OptionalStream API、CompletableFutureなどのコアJava8機能をサポートするようになりました。

この簡単な記事では、これらをフレームワークで使用する方法の例をいくつか紹介します。

2. Optional

CRUDリポジトリメソッドから始めましょう。これで、結果がOptionalになります。

public interface CrudRepository extends Repository {

    Optional findById(ID id);

}

Optionalインスタンスを返す場合、値が存在しない可能性があることを示す便利なヒントです。 オプションの詳細については、hereを参照してください。

ここで行う必要があるのは、戻り値の型をOptionalとして指定することだけです。

public interface UserRepository extends JpaRepository {

    Optional findOneByName(String name);

}

3. Stream API

Spring Dataは、Java 8の最も重要な機能の1つであるStreamAPIのサポートも提供します。

以前は、複数の結果を返す必要があるときは常に、コレクションを返す必要がありました。

public interface UserRepository extends JpaRepository {
    // ...
    List findAll();
    // ...
}

この実装の問題の1つは、メモリの消費でした。

取得したすべてのオブジェクトを熱心にロードして保持する必要がありました。

ページングを活用することで改善できます。

public interface UserRepository extends JpaRepository {
    // ...
    Page findAll(Pageable pageable);
    // ...
}

シナリオによってはそれで十分ですが、他のシナリオでは、データを取得するために必要なリクエストの数が多いため、ページ付けは実際には方法ではありません。

Java 8Stream APIおよびJPAプロバイダーのおかげで–define that our repository method returns just a Stream of objectsが可能になりました:

public interface UserRepository extends JpaRepository {
    // ...
    Stream findAllByName(String name);
    // ...
}

Spring Dataはプロバイダー固有の実装を使用して結果をストリーミングします(HibernateはScrollableResultSetを使用し、EclipseLinkはScrollableCursorを使用します)。 メモリ消費量とデータベースへのクエリ呼び出しの量を削減します。 そのため、前述の2つのソリューションよりもはるかに高速です。

Processing data with a Stream requires us to close a Stream when we finish it

これは、Streamclose()メソッドを呼び出すか、try-with-resourcesを使用して実行できます。

try (Stream foundUsersStream
  = userRepository.findAllByName(USER_NAME_ADAM)) {

assertThat(foundUsersStream.count(), equalTo(3l));

We must also remember to call a repository method within a transaction。 それ以外の場合は、例外が発生します。

org.springframework.dao.InvalidDataAccessApiUsageExceptionStreamを実際に消費できるように、接続を開いたままにする周囲のトランザクションなしでストリーミングクエリメソッドを実行しようとしています。 ストリームを消費するコードが@Transactionalまたは(読み取り専用)トランザクションを宣言する他の方法を使用していることを確認してください。

4. CompletableFuture

非同期メソッド実行のためのSpring Data repositories can run asynchronously with the support of Java 8’s CompletableFutureおよびSpringメカニズム:

@Async
CompletableFuture findOneByStatus(Integer status);

このメソッドを呼び出すクライアントはすぐにフューチャーを返しますが、メソッドは別のスレッドで実行を継続します。

CompletableFutureの処理に関する詳細は、hereにあります。

5. 結論

このチュートリアルでは、Java 8の機能がSpring Dataとどのように連携するかを示しました。

例の完全な実装は、over on Githubで利用できます。