[hibernate-dev] [OGM] Demarcating units of work

Gunnar Morling gunnar at hibernate.org
Wed May 6 09:16:16 EDT 2015


2015-05-06 14:19 GMT+02:00 Emmanuel Bernard <emmanuel at hibernate.org>:

> It’s an interesting idea.
> Let me give you the reasons why I think the transaction API has merits.
>
> There is already a notion of UnitOfWork that was named Conversation in
> Seam / CDI. But its span is potentially longer than the span of the updates
> window. The closer notion of a UnitOfWork is an EntityManager or a Session.

By introducing @UnitOfWork, you forgo all the integration between
> application frameworks and transactions. Here you offer a solution for CDI
> but we would need one for Java EE non CDI and one for Spring and one for
> Grails and one for…


The current integrations would continue to work. So e.g. EJB non-CDI would
still use JTA as is today. I don't find it to be a big problem there, as
it's much more under the covers (which is why it's nice to show EJBs in
demos ;). Same for the others basically.

I understand you reluctance to call a Tiger a Cat but they are commonly
> referred as Cats.
> Back to our problem, you either
> - teach people that transaction is not what they might understand of
> transactions - if they even know what that means these days ;)
> - teach them a new concept that suspiciously looks like a transaction
> anyways and force them to do the integration of that “thing” with their
> universe.
>

I'd prefer the latter. The good thing is that it is up to us to
describe/document what the "thing" is, so we can manage expectations
towards it, far better then when using the term "transaction" which
automatically raises certain expectations (smart people will wonder how we
make it work, others may even fall into the trap and believe it is actually
TX).

>
> I like the exploration of lamda usage for the Hibernate APIs but we
> probably should think about it in the larger scheme of ORM and in this
> async API trend. What could we do.
> Note also that your example reflects a simple example where you *whole*
> unit of work is very simple and does not span services / DAOs. If it spans
> services / DAOs, then the lambda approach sort of fails a little by as you
> need to reach the session from within these nested service calls.
>

Yes, that is a good point. Probably we'd also need something like
beginUnitOfWork(). Maybe something like this is the better approach:

    session.buildUnitOfWork()
        .onFailedGridDialectOperation( context -> {
            // e.g. log failed op
            return ErrorHandlingStrategy.ABORT;
        } )
        .onRollback( context -> {
            // e.g. log applied ops
        } )
        .begin();

    session.persist( order );
    session.persist( customer );

    session.finishUnitOfWork();



> I am relatively open on these proposals but we need to flesh them out much
> better before we can consider them seriously (say for the next sprint).
>

Sure, it's not fully worked out, I just wanted to quickly gauge general
interest in this. I will file an issue.

>
>
> > On 06 May 2015, at 11:01, Gunnar Morling <gunnar at hibernate.org> wrote:
> >
> > Hi,
> >
> > When talking to people about OGM, there is always that awkward moment
> when
> > you need to explain that TX demarcation is required also for
> > non-transactional data stores.
> >
> > While it makes sense for our purposes (we use the "TX cycle" to optimise
> > the work sent to the backend etc.), I can understand people who find that
> > odd API-wise. So I was thinking about how this could be improved.
> >
> > When it comes to CDI, a more "neutral" annotation (and a portable
> extension
> > examining it) than @Transactional could be helpful:
> >
> >    @UnitOfWork
> >    public void saveOrderAndCustomer(Order order, Customer customer) {
> >        session.persist( order );
> >        session.persist( customer );
> >    }
> >
> > By means of the @UnitOfWork annotation it would be expressed that the
> > entire method should run as one "transaction". This also could be used to
> > specify an error handler for our new API to be applied for this unit of
> > work:
> >
> >    @UnitOfWork(errorHandler=FailedOpsLoggingHandler.class)
> >    public void saveOrderAndCustomer(Order order, Customer customer) {
> ... }
> >
> > In non-managed environments, Java-8-style Lambda expressions could be
> > leveraged nicely to achieve the same:
> >
> >    session.runUnitOfWork( () -> {
> >        session.persist( order );
> >        session.persist( customer );
> >    };
> >
> > This should feel much nicer to e.g. users of the MongoDB backend than
> > invoking session.getTransaction().begin()/commit(). It also plays greatly
> > together with the error handling stuff:
> >
> >    session.buildUnitOfWork( () -> {
> >        session.persist( order );
> >        session.persist( customer );
> >    } )
> >    .onFailedGridDialectOperation( context -> {
> >        // e.g. log failed op
> >        return ErrorHandlingStrategy.ABORT;
> >    } )
> >    .onRollback( context -> {
> >        // e.g. log applied ops
> >    } )
> >    .run();
> >
> > Of course something equivalent could be done for Java 7, but it'd
> probably
> > look not as concise.
> >
> > Any thoughts?
> >
> > Cheers,
> >
> > --Gunnar
> > _______________________________________________
> > hibernate-dev mailing list
> > hibernate-dev at lists.jboss.org
> > https://lists.jboss.org/mailman/listinfo/hibernate-dev
>
>


More information about the hibernate-dev mailing list