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

Steve Ebersole steve at hibernate.org
Wed Sep 14 16:35:53 EDT 2016


Naming aside, my favorite approach is to have an "executor" available from
SessionFactory for accepting this functional-interface (lambda).  The
executor would be configured with whether to isolate the work and whether
to transact it.  Something like:

Executor getExecutor(boolean isolated, boolean transacted);

And then, Executor defines:

<T> T doInSession(Function<Session,T> work)

so all-told:

factory.getExecutor( true, true ).doInSession( session -> ... )

As Sanne says though we need a better name for Executor

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

> Most transaction systems do not support nested transactions
>
>
> On Wed, Sep 14, 2016 at 3:13 PM Sanne Grinovero <sanne at hibernate.org>
> wrote:
>
>> On 14 September 2016 at 21:02, Steve Ebersole <steve at hibernate.org>
>> wrote:
>> > Also, why do you keep defining this in terms of Session, rather than
>> > SessionFactory?
>>
>> I mentioned that same doubt in my first email of this thread.
>> I think I prefer Session as that's what people interact with most of
>> the time, and it's a better choice if we opt to make this a nested
>> transaction of the current one; if it's meant to be totally
>> independent yes then we should probably consider the SF.
>>
>> >
>> >
>> > On Wed, Sep 14, 2016 at 3:01 PM Steve Ebersole <steve at hibernate.org>
>> wrote:
>> >>
>> >> "Better" according to whom? ;)
>> >>
>> >> I personally very much dislike the kind of API explosion this kind of
>> >> thing leads to.
>> >>
>> >>
>> >> On Wed, Sep 14, 2016 at 2:59 PM Sanne Grinovero <sanne at hibernate.org>
>> >> wrote:
>> >>>
>> >>> On 14 September 2016 at 20:32, 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?
>> >>>
>> >>> I had only the (new) transaction case in mind, but sure you could add
>> >>> a `transacted` boolean parameter.
>> >>>
>> >>> Or we make it explicit with a better method name:
>> >>>
>> >>> s.executeInSubtransaction( session -> session.save(...) );
>> >>>
>> >>> Thanks,
>> >>> Sanne
>> >>>
>> >>>
>> >>> >
>> >>> > 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