[hibernate-dev] [OGM] Demarcating units of work
Sanne Grinovero
sanne at hibernate.org
Wed May 6 05:43:19 EDT 2015
Making the user work with a Transaction API even though the storage
doesn't implement it "at all" isn't a novelty of OGM. Remember MySQL's
MyISAM ?
It's supported by Hibernate, and while InnoDB might be on the rise
compared to MyISAM, it's not dead.
The range of transactional capabilities of different engines varies a
lot in many subtle details which are hard to classify under a single
standard API; In my view not supporting any transactional capability
is just a very low form of transaction capabilities :)
I would totally agree with you that this is a concrete and interesting
problem to solve, but I don't think it's something for OGM to do.
Sanne
On 6 May 2015 at 10:31, Gunnar Morling <gunnar at hibernate.org> wrote:
> 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