java - 使用 Spring Data JPA Stream 获取数据
问题描述
下面是我的控制器
public class TestController {
@PersistenceContext
EntityManager entityManager;
@Autowired
ProductAltRepository productAltRepository;
@GetMapping("/findAll")
@Transactional(readOnly = true)
public void findAll() {
Stream<ProductAltRelEntity> productAltRelEntities = productAltRepository.findAllProductAlts();
List<ProductAltRelEntity> productAlts = Lists.newArrayList();
productAltRelEntities.forEach(x -> {
productAlts.add(x);
entityManager.detach(x);
});
}
这是存储库
@Repository
@Transactional
public interface ProductAltRepository
extends JpaRepository<ProductAltRelEntity, Long>, JpaSpecificationExecutor<ProductAltRelEntity>{
@QueryHints(value = { @QueryHint(name = HINT_FETCH_SIZE, value = "" + Integer.MIN_VALUE),
@QueryHint(name = HINT_CACHEABLE, value = "false"), @QueryHint(name = HINT_READONLY, value = "true"), })
@Query("SELECT p FROM ProductAltRelEntity p")
public Stream<ProductAltRelEntity> findAllProductAlts();
}
要求是findAll(),分页给OOM,所以想用Stream,但是遇到异常。
[WARN] org.hibernate.engine.jdbc.spi.SqlExceptionHelper - SQL Error: 17068, SQLState: 99999
2019-11-15 12:30:31.468 错误 7484 --- [nio-8082-exec-1] ohengine.jdbc.spi.SqlExceptionHelper:调用中的参数无效:setFetchSize [ERROR] org.hibernate.engine。 jdbc.spi.SqlExceptionHelper - 调用中的参数无效:setFetchSize 2019-11-15 12:30:31.793 错误 7484 --- [nio-8082-exec-1] cseddeGlobalExceptionHandler:未处理的异常:org.springframework.orm。 jpa.JpaSystemException:无法使用滚动执行查询;嵌套异常是 org.hibernate.exception.GenericJDBCException:无法使用滚动执行查询 原因:org.hibernate.exception.GenericJDBCException:无法使用滚动执行查询 原因:java.sql.SQLException:调用中的参数无效:setFetchSize
解决方案
阅读错误日志,您需要将流式代码放在 try 块中,即
try(Stream<ProductAltRelEntity> productAltRelEntities = productAltRepository.findAllProductAlts()){
List<ProductAltRelEntity> productAlts = Lists.newArrayList();
productAltRelEntities.forEach(x -> {
productAlts.add(x);
entityManager.detach(x);
});
} catch(Exception ex) {ex.printStackTrace();}
我注意到的另一件事是您不需要将 @Transactional 放入 ProductAltRepository 中,因为您已经将它放入了 TestController 中。
为了流式传输结果,我们需要满足三个条件:
Forward-only resultset
Read-only statement
Fetch-size set to Integer.MIN_VALUE
Spring Data 似乎已经设置了 Forward-only,因此我们不必为此做任何特别的事情。您的代码示例已经在 TestController 中有 @Transactional(readOnly = true) 注释,足以满足第二个条件,因此 @QueryHint(name = HINT_READONLY, value = "true") 没有用。fetch-size 似乎很有用。
以下是我的一个项目的摘录:
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.JpaSpecificationExecutor;
import org.springframework.data.jpa.repository.Query;
import static org.hibernate.jpa.QueryHints.HINT_FETCH_SIZE;
public interface IssueRepo extends JpaRepository<Issue, Long>, JpaSpecificationExecutor<Issue> {
@QueryHints(value = @QueryHint(name = HINT_FETCH_SIZE, value = "" + Integer.MIN_VALUE))
@Query("select t from Issue t ")
Stream<Issue> getAll();
}
控制器
public class ManageIssue {
@GetMapping("all/issues")
@Transactional(readOnly = true)
public String getAll() {
System.out.println("Processing Streams ...");
try(Stream<Issue> issuesList = issueRepo.getAll()){
issuesList.forEach(issue -> {
System.out.println(issue.getId()+" Issue "+issue.getTitle());
});
} catch(Exception ex) {ex.printStackTrace();}
return "All";
}
}
推荐阅读
- tarsosdsp - 执行 FFT.forwardTransform() 时单击声音
- jquery - 吐司可见但不应该?
- javascript - 我如何才能简单地解决对象中对象中缺少的 JS 属性?
- php - PHP-LARAVEL 6 创建的类别返回 404
- google-apps-script - 如何使用谷歌分析跟踪谷歌表格中的行值发送的电子邮件?
- python - 子列表的唯一元素取决于子列表中的特定值
- environment-variables - Bazel - 如何从环境文件中读取字符串?
- javascript - Service Worker 未收到推送消息
- c# - C# 将对象解析为 Google BigQuery 行
- javascript - 任何机会我都可以用 Apexcharts.js 构建这个径向条