Spring中的事务和流 [英] Transactional and Stream in 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.
尝试:
- 重构并称之为
@Transactional
来自您上下文中其他类的方法,或 - 按自动装配类本身并以这种方式调用
@Transactional
方法。
- Refactoring and call this
@Transactional
method from another class in your context, or - 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屋!