[hibernate-dev] Lambda usage to run a code block in an isolated transaction

Steve Ebersole steve at hibernate.org
Wed Sep 14 15:59:53 EDT 2016


As another option we could define something like this on SF:

<T> T doInIsolatedSession(BiFunction<Session,Boolean,T> work);
<T> T doInIsolatedSession(Function<Session,T> work);

The spec here would be to make sure any current transaction is suspended
(JTA), a new Session opened, the function performed and the suspended
transaction is resumed (JTA).  In between the Boolean would dictate whether
a new Transaction is started.

I also considered just the second form and having the function manage the
new transaction as needed.  The "difficulty" with that is back to the same
#getTransaction (API) versus #accessTransaction (SPI) issue you already
discovered.  Perhaps it could be reasonable to either expect the function
to cast to SessionImplementor or to define this based on SessionImplementor
rather than Session; dunno.



On Wed, Sep 14, 2016 at 2:32 PM Steve Ebersole <steve at hibernate.org> wrote:

> The problem with "execute in isolation" here is that the "isolation"
> aspect refers to being isolated from any current transaction.  It says
> nothing about whether that stuff-to-execute should itself be transacted.
> This is why, for example, you see IsolationDelegate accept a `transacted`
> boolean argument.
>
> How would you propose we pass such a flag in this case?  Or are you
> proposing that this always start a (new) transaction?
>
> On Wed, Sep 14, 2016 at 1:39 PM Sanne Grinovero <sanne at hibernate.org>
> wrote:
>
>> Today porting some benchmark code to Hibernate ORM 5.2 I had several
>> difficulties around the fact that the code now needs to be different
>> depending on transactions being container managed or not.
>>
>> My goal was to have a single benchmark test which I could compile once
>> and run in either JavaSE or CMT; with some help from Steve I figured
>> the necessary incantations out but ... it looks very unpractical.
>>
>> One way is to use an isolation delegate, which looks like this:
>>
>> final SessionImplementor session = (SessionImplementor) s;
>>
>> session.getTransactionCoordinator().createIsolationDelegate().delegateWork(
>>    new WorkExecutorVisitable() {
>>       @ Override
>>       public Object accept(WorkExecutor executor, Connection
>> connection) throws SQLException {
>>          /// Some work with PreparedStatement on Connection..
>>       }
>> }, true );
>>
>> This worked fine for some raw SQL used for the benchmark
>> initialization, but in another case I'd prefer to use the Session API
>> rather than dealing with PreparedStatements and native connections;
>> it looks like we don't have an equivalent "run code in isolation" for
>> the Session ?
>>
>> It would be great if I could just pass a lambda to a Session and have
>> this executed on a "child Session" in the scope of a "child
>> Transaction", or just start and commit a transaction if there isn't
>> one.
>>
>> s.executeInIsolation( session -> session.save(...) );
>>
>> So I'd expect that details like how to begin the transaction, how it
>> should be committed (or rolled back in case of exceptions), how to
>> lookup a TransactionManager, and especially how to not leak resources
>> should be handled for the user.
>>
>> Obviously the inner Session instance is a different one than the
>> outer, so any data returned by this block should be considered
>> detached; maybe this limitation would be clearer if the method was
>> hosted on SessionFactory or StatelessSession instead?
>> Although it wouldn't necessarily have the limitations of a
>> StalessSession, and it would be nice to have the inner transaction
>> behave as a nested one when there's already one in the host Session.
>>
>> Looking forward for comments and improvement ideas :)
>>
>> Thanks,
>> Sanne
>> _______________________________________________
>> 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