简体   繁体   中英

Spring / Hibernate @Transactional not flushing transaction if followed by a second @Transactional call

I have a weird behaviour in my Spring Boot App.

The app have the OpenSessionInView to false .

I have a Controller and a Service exposing 2 methods with annotation @Transactionnal .

Application.properties:

spring.jpa.open-in-view=false

My service:

@Service
public class MyService {
        @Transactional(transactionManager = "myTx")
        public void doA(Integer objectId) {
                Object o = repo.findMyObject(objectId);
                updateMyObject(o);
                repo.save(o);
        }

        @Transactional(transactionManager = "myTx")
        public void doB(Integer objectId) {
                Object o = repo.findMyObject(objectId);
                updateMyObjectDifferently(o);
                repo.save(o);
        }
}

My Controller (case 1):

@RequestMapping("/do/{myId}")
    public String do(Model model, HttpServletRequest request) {

        service.doA(myId);
        service.doB(myId);

        return "page";
    }

With SQL in debug, I see that the SELECT queries are performed during the call to the service. But I see only 1 flush (several UPDATES) , and it's done when service.doB() is finished and the TransactionInterceptor around the method launch the method invokeWithinTransaction which is weird.

As both method have @Transactional, I was hoping to see 2 flush : the first flush just at the end of service.doA() and a second flush at the end of service.doB().

What is more weird is that if I comment the second call, so

My Controller (case 2):

@RequestMapping("/do/{myId}")
    public String do(Model model, HttpServletRequest request) {

        service.doA(myId);
        //service.doB(myId);

        return "page";
    }

In case 1, it's like service.doA() knows that a second call will arrive just after on the same object, so it does not commit/flush the transaction and wait for the end of service.doB().

Why do I see only 1 flush? Is it because both calls are on the some DB object?

I thought my knowledge of @Transactional were ok. But now, I am lost.

Hibernate will detect if an object really is dirty and avoid sending an UPDATE statement if it's not necessary. I assume that your updateMyObject is simply not changing the state of the entity with respect to the state it had initially when it was loaded.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM