Spring中的事务和流 [英] Transactional and Stream in Spring

查看:541
本文介绍了Spring中的事务和流的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I try to understand why this code doesn't work

在组件中:

@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或任何其他方式声明(只读)事务。

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.


推荐答案

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

One key thing about Spring is that many annotated features use proxies to provide the annotation functionality. That is @Transactional, @Cacheable and @Async all rely on Spring detecting those annotations and wrapping those beans in a proxy bean.

在这种情况下,代理方法只能在调用时使用班级,而不是来自 班级。请参阅关于这个话题。

That being the case, a proxied method can only be used when invoked on the class and not from within the class. See this about the topic.

尝试:


  1. 重构并称之为 @Transactional 来自您上下文中其他类的方法,或

  2. 自动装配类本身并以这种方式调用 @Transactional 方法。

  1. Refactoring and call this @Transactional method from another class in your context, or
  2. By self-autowiring the class into itself and calling the @Transactional method that way.

演示(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);
           }
   }
}

这篇关于Spring中的事务和流的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆