web-dev-qa-db-ja.com

Java 8ストリームがJDBC接続を閉じない)を返すSpringリポジトリメソッド

私はSpring dataリポジトリ:

@Repository
interface SomeRepository extends CrudRepository<Entity, Long> {
    Stream<Entity> streamBySmth(String userId);
}

私はいくつかのSpringBeanでそのメソッドを呼び出しています:

@Scheduled(fixedRate = 10000)
private void someMethod(){
    someRepository.streamBySmth("smth").forEach(this::callSomeMethod);
}

MySQLデータベースを使用しています。また、メソッドの呼び出しが成功した後にアプリケーションを実行すると、例外がスローされます。

o.h.engine.jdbc.spi.SqlExceptionHelper   : SQL Error: 0, SQLState: 08001
o.h.engine.jdbc.spi.SqlExceptionHelper   : Could not create connection to database server.
o.s.s.s.TaskUtils$LoggingErrorHandler    : Unexpected error occurred in scheduled task.

org.springframework.dao.DataAccessResourceFailureException: Unable to acquire JDBC Connection; nested exception is org.hibernate.exception.JDBCConnectionException: Unable to acquire JDBC Connection

Springによって接続が適切に閉じられなかったようです。メソッドの戻り値をListからStreamに変更した場合、正しく機能します。

PDATE: SpringBootのバージョンは1.4.1.RELEASEです

10

リファレンスドキュメントに明確に記載されている であるため、Streamsはtry-with-resourcesブロックとともに使用する必要があります。

また、周囲のメソッドに@Transactionalアノテーションを付けて、ストリームの消費時に(読み取り専用)トランザクションを開いたままにしておくようにしてください。それ以外の場合は、デフォルト設定が適用され、リポジトリメソッドの戻り時にリソースが解放されようとします。

@Transactional
public void someMethod() {

  try (Stream<User> stream = repository.findAllByCustomQueryAndStream()) {
    stream.forEach(…);
  } 
}
12
Oliver Drotbohm

@Transactional(readOnly = true)とパブリックアクセス修飾子を使用すると、問題が解決します。他のアクセス修飾子は機能しません。

1
user666