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(a)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(a)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(a)lists.jboss.org
>
https://lists.jboss.org/mailman/listinfo/hibernate-dev
>