Hibernate-reactive: Enhancement - Integration with spring @Transactional annotation

Created on 20 May 2021  ·  16Comments  ·  Source: hibernate/hibernate-reactive

Hi,

we are on the ongoing evaluation of hibernate reactive to replace our current software software composed of postgres-db+spring boot+spring data+r2dbc. We faced a lot of limitation using r2dbc and we wanted to reuse the large knowledge we already have around Hibernate.
We almost refactored a full micro-service, re-write our own spring-data (generic repository) and it looks really good.

One of the major issue developers are raising in the option to use declarative transaction management (using annotation) instead of programmatic.

We know that it's not the purpose of Hibernate reactive to implement such mechanism, but to the frameworks (Spring, Quarkus...) that integrates with Hibernate, as it was done for the standard Hibernate. Even if we want to do it by ourselves, the transaction API in Hibernate reactive is not the same as the standard Hibernate API and there is no API to interact with the transaction manager.

I will be happy if we can get your comments about this (and even more if you can :smiley:), and if you still think we can do it to propose the general guidelines because we currently have no clue how to do it.
Thanks

problem

All 16 comments

Well I suppose that Spring has some sort of interceptor concept where you could use annotations to bind an interceptor to a bean method call. If you call withTransaction() from within an interceptor like that, and then delegate to the bean method, that's all declarative transaction management is. Really it should be only a few lines of code. (At least it would be in CDI, I'm less sure about spring.)

The only subtlety is that you need a way to detect if there is a transaction already bound to the current reactive stream. In our stack that would be done using MP Contexts. No idea how that's done in Spring land.

(OTOH if you're asking about how to integrate with with an XA transaction manager, well, that's a whole different can of worms, and is not really practical with the reactive driver right now. We don't yet have any truly reactive transaction managers.)

Right now, we have no need for distributed transaction

Then an interceptor that calls SessionFactory.withTransaction() should work fine.

Will try this way and update. thanks

@gavinking it looks that Spring implements the @Transactional using Aspect. It is not really so important, but it may be also simpler for us to implement.
But I think we cannot do it only if you expose an API for openTransaction() commitTransaction() and rollbackTransaction() in the Stage class, as we have a openSession() and closeSession() API. I think the transaction object is needed, and the withTransaction is not enough.
Does it make sense ?

There should be some sort of notion of an "around" interceptor which lets you wrap and forward to the method.

(It's true that you can't do it with before/after interceptors.)

@gavinking can you please elaborate about what you wrote before "In our stack that would be done using MP Contexts." to check if a transaction is already bound in the current stream? Can you refer to code, or tests that was written. Same for session, how can I understand that a session is already open in the current stream.
Thanks.

Look, I have no idea how you do that in Spring. You need some sort of construct that is sorta like a threadlocal, but a local bound to the current reactive stream instead of the thread. I'm sure they must have something.

I'm currently not going to use spring @Transactional but implement our own transactional annotation to avoid getting too much deeper into Spring. So my previous question was related to your sentence "In our stack that would be done using MP Contexts".

"our stack" == Quarkus.

I'm saying you have to find something similar in the Spring environment.

Because if you can't bind a value to the current reactive stream, then you can't have declarative transactions, simple as that, and you'll just have to manage transactions "manually". (Which is actually super-simple by just calling withTransaction(). I really don't get why people think they need an annotation for that.)

But I'm sure there must be some way to do it. You're just asking the wrong person.

Closing: superseded by #782.

@yaakov-berkovitch with the stuff I'm putting into place with #779 it should be even easier for you to implement this.

@gavinking Thanks!!

Was this page helpful?
0 / 5 - 0 ratings