Spring 中的事务和流

Tho*_*ras 4 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);
    }
}
Run Code Online (Sandbox Code Playgroud)

和存储库:

public interface PersonRepository extends JpaRepository<Person, Long> {
    Stream<Person> findTop10ByFirstName(String firstName);
}
Run Code Online (Sandbox Code Playgroud)

我得到:

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

Dov*_*vmo 8

Spring 的一个关键点是许多带注释的特性使用代理来提供注释功能。也就是说@Transactional@Cacheable而且@Async全部依赖于Spring检测这些标注,并在代理bean包装的咖啡豆。

在这种情况下,代理方法只能在类调用使用,而不能从类调用。请参见的话题。

尝试:

  1. 重构并@Transactional从上下文中的另一个类调用此方法,或
  2. 通过将类自动装配到自身中并以@Transactional这种方式调用方法。

证明(1)

public class MyOtherClass {

    @Autowired
    private MyTestStreamClass myTestStreamClass;

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

}
Run Code Online (Sandbox Code Playgroud)

证明(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);
           }
   }
}
Run Code Online (Sandbox Code Playgroud)