Repository

定义一个根据类型查询考题的接口

  1. @Repository
  2. public interface ExamQuestionDao extends JpaRepository<ExamQuestion, Integer> {
  3. /**
  4. * 根据考题类型查询考题
  5. *
  6. * @param questionType {@link com.lixin.newworld.domain.enums.QuestionType} 考题类型
  7. * @return {@link List<ExamQuestion>} 考题
  8. */
  9. Stream<ExamQuestion> findAllByType(QuestionType questionType);
  10. }

Client

简单写了一个单元测试来调用

  1. @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
  2. public class ExamQuestionDaoTests {
  3. @Autowired
  4. private ExamQuestionDao examQuestionDao;
  5. @Test
  6. public void testJPA() {
  7. long count = examQuestionDao.findAllByType(QuestionType.JUDGE)
  8. .filter(q -> q.getType() != QuestionType.JUDGE)
  9. .count();
  10. assert count == 0;
  11. }
  12. }

Error

Duang,翻车了!抛出以下异常👇

org.springframework.dao.InvalidDataAccessApiUsageException: You’re trying to execute a streaming query method without a surrounding transaction that keeps the connection open so that the Stream can actually be consumed. Make sure the code consuming the stream uses @Transactional or any other way of declaring a (read-only) transaction.

报错原因是:为了保持 Stream 连接打开,必须保证消费 Stream 的代码处于事务控制!

Fix

根据报错的提示,需要在消费 Stream 代码处添加 @Transactional 注解即可解决上述报错!最终无误代码如下

  1. @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.NONE)
  2. public class ExamQuestionDaoTests {
  3. @Autowired
  4. private ExamQuestionDao examQuestionDao;
  5. @Test
  6. @Transactional(readOnly = true)
  7. public void testJPA() {
  8. long count = examQuestionDao.findAllByType(QuestionType.JUDGE)
  9. .filter(q -> q.getType() != QuestionType.JUDGE)
  10. .count();
  11. assert count == 0;
  12. }
  13. }

再执行一次,测试通过,可以开始愉快的玩耍 Stream API 了!