Transactional and Stream in Spring

后端 未结 1 486
天涯浪人
天涯浪人 2021-01-01 06:03

I try to understand why this code doesn\'t work

In component:

@PostConstruct
public void runAtStart(){

    testStream();
}

@Transactional(readOnly          


        
相关标签:
1条回答
  • 2021-01-01 06:50

    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.

    Try:

    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.

    To demonstrate (1):

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

    To demonstrate (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);
               }
       }
    }
    
    0 讨论(0)
提交回复
热议问题