春天的交易和流

时间:2018-08-19 23:29:42

标签: spring java-8

我试图理解为什么这段代码不起作用

在组件中:

@PostConstruct
public void runAtStart(){

    testStream();
}

@Transactional(readOnly = true)
public void testStream(){
    try(Stream<Person> top10ByFirstName = personRepository.findTop10ByFirstName("Tom")){
        top10ByFirstName.forEach(System.out::println);
    }
}

和存储库:

public interface PersonRepository extends JpaRepository<Person, Long> {
    Stream<Person> findTop10ByFirstName(String firstName);
}

我得到:

  

org.springframework.dao.InvalidDataAccessApiUsageException:您正在尝试在没有周围事务的情况下执行流查询方法,该事务使连接保持打开状态,从而可以实际使用Stream。确保使用流的代码使用@Transactional或其他任何声明(只读)事务的方式。

1 个答案:

答案 0 :(得分:1)

关于Spring的关键一点是,许多带注释的功能都使用代理来提供注释功能。即@Transactional@Cacheable@Async都依赖于Spring检测这些注释并将这些bean包装在代理bean中。

在这种情况下,仅当在类中的调用该代理方法时,才可以使用该方法。有关该主题,请参见this

尝试:

  1. 在您的上下文中从另一个类重构并调用此@Transactional方法,或者
  2. 通过self-autowiring将该类插入自身并以这种方式调用@Transactional方法。

演示(1)

public class MyOtherClass {

    @Autowired
    private MyTestStreamClass myTestStreamClass;

    @PostConstruct
    public void runAtStart(){
        // This will invoke the proxied interceptors for `@Transactional`
        myTestStreamClass.testStream();
    }

}

演示(2)

@Component
public class MyTestStreamClass {

   @Autowired
   private MyTestStreamClass myTestStreamClass;

   @PostConstruct
   public void runAtStart(){
       // This will invoke the proxied interceptors for `@Transactional` since it's self-autowired
       myTestStreamClass.testStream();
   }

   @Transactional(readOnly = true)
   public void testStream(){
       try(Stream<Person> top10ByFirstName = personRepository.findTop10ByFirstName("Tom")){
               top10ByFirstName.forEach(System.out::println);
           }
   }
}