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

Gunnar Morling gunnar at hibernate.org
Wed May 6 05:31:06 EDT 2015


2015-05-06 11:13 GMT+02:00 Sanne Grinovero <sanne at hibernate.org>:

> Did you consider that the existing definition of "Transaction
> boundaries" can have different levels of isolation and guarantees,
> depending on how the underlying components are configured?
>

I didn't, but that's exactly the point. Talking (API-wise) about
"transactions", "isolation levels" does not really make sense if the
underlying backend is non-transactional by its nature.

We just piggy-back on the transaction cycle from ORM to control flushes,
but this doesn't give you any sort of transactional guarantees if not
natively supported. If you e.g. do an explicit flush() in the middle of a
"transaction", these changes will be visible to other clients, no matter
what kind of isolation level has been configured somewhere.

I do agree with you that it's kind of weird that people write code
> without making transactional requirements explicit in the code, but it
> seems that the trend is to abstract from that and use the
> "Transaction" term as a "Unit of work".
>

Where do you see this trend? Surely not e.g. in MongoDB or CouchDB? It's
exactly the usage of the term "transaction" which I find irritating for
these stores and which I thus seek to avoid.

For example I find it strange that - in Java - one has to configure
> the isolation levels of transactions to the safest (least efficient)
> option possible among the types his *various* use cases require. It's
> pretty obvious that it would be more efficient to choose those levels
> as "profiles" based on use case, possibly bean or even method level.
> I guess that's were complex applications split up in multiple deployments..
>
> What is concerning is that the average developer will write Java code
> making assumptions on the underlying transaction guarantees, and will
> rarely communicate those as requirements to whoever configures it.
> Is that what you aim to solve?
>
> Not really. What I aim to solve is to avoid making the user work with APIs
which suggest certain kinds of guarantees which in reality are not there
for certain backends.

>
>
>
> On 6 May 2015 at 10: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