私は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です
リファレンスドキュメントに明確に記載されている であるため、Stream
sはtry-with-resourcesブロックとともに使用する必要があります。
また、周囲のメソッドに@Transactional
アノテーションを付けて、ストリームの消費時に(読み取り専用)トランザクションを開いたままにしておくようにしてください。それ以外の場合は、デフォルト設定が適用され、リポジトリメソッドの戻り時にリソースが解放されようとします。
@Transactional
public void someMethod() {
try (Stream<User> stream = repository.findAllByCustomQueryAndStream()) {
stream.forEach(…);
}
}
@Transactional(readOnly = true)とパブリックアクセス修飾子を使用すると、問題が解決します。他のアクセス修飾子は機能しません。