0

I have two classess as below.

@Component
@RequiredArgsConstructor
public class SomeScheduler {
    
    private final SomeService someService;

    @Scheduled( ... )
    void doScheduledJob() {
         someService.doJob();
    }
}
@Service
@RequiredArgsConstructor
@Transactional
public class SomeService {
    
    private final SomeRepository someRepository;

    public void doJob() {
        someRepository.findByCustomized();
        
        ...
    }
}

The problem is that SomeService is working without @Transactional.

With configuration in application.yml logging.level.org.springframework.transactional.interceptor: DEBUG, I found that there are some logs like No need to create transaction for [org.springframework.data.jpa.repository.support.SimpleJpaRepository.findByCustomized]: This method is not transactional.

What I wanna know is :

  1. There is no transctional on service method. Why ? (If I change with MANDATORY propagation, it throws exception)
  2. my repository method which has @Query annotation works. I've thought that 'JPA requires transaction' but it wasn't. Why ?

I've searched this for a while, but couldn't understand. Can any one explain this or show me any article about ?

Thank you.

cjlee
  • 378
  • 3
  • 10

1 Answers1

1

looks like "findByCustomized" is a non-modifiable query method (aka select), there is no need in transaction thus

  • thanks. I was mistaken about jpa and transaction as all jpa queries always require transcation. But how about the question 1 ? Why there is no transaction on service method ? – cjlee Aug 18 '22 at 01:50
  • There is a JPA transaction with readonly=true parameter, used for some query optimization inside only. At DB level, there is no need to start any transaction. There is a good explanation [here](https://stackoverflow.com/a/10466591/13781909) – Danny Briskin Aug 18 '22 at 14:29
  • There are some modifying queries in `doJob` method. Also, I created new service method to test which has two `save` method of repository and throws exception after save. When I called the test method with `Scheduled` annotation, the result was not expeceted ( two `save`s were committed ) which means, there wasn't transcation on service method – cjlee Aug 20 '22 at 19:08
  • Technically, @Scheduled creates a Runnable with your method call inside, with all annotations the method has (including those from its class). It means that the scheduler will run doJob() with @Transactional(propagation=Propagation.REQUIRED <- a default value) You can change propagation level to Propagation.NEVER for example. It will not create transactions on Selects and will create for modifying queries. – Danny Briskin Aug 22 '22 at 14:51
  • do you use a custom transaction manager or a default springboot one? – Danny Briskin Aug 22 '22 at 14:52
  • I've drilled down the codes associated with `@Scheduled` and `@Transactional` for dozens of hours and finally got what caused this problem. In short, I've forgot to add 'public' modifier on `doJob()` method. :( When I searched about this problem, I saw lots of articles saying "you need to seperate `scheduled` class and `transactional` class. (e.g. https://stackoverflow.com/a/45356139/11686638) So I thought that there are some unknown things about both annotations. – cjlee Aug 22 '22 at 15:57
  • Actually, there's nothing to worry about this(I worried about so many other cases like 'is it caused from multi-thread ? or transaction manager ? ... '), and it works well as I expected with 'public' modifier. I'm really appreciate for your efforts – cjlee Aug 22 '22 at 15:59