-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 12 posts ] 
Author Message
 Post subject: Sharing a transaction with multiple sessions
PostPosted: Mon Nov 20, 2017 4:15 am 
Newbie

Joined: Wed Nov 18, 2015 10:02 am
Posts: 7
I am working on upgrading Hibernate from 4.3 to 5.2. It seems the system I’m working with shares a transaction with multiple sessions. More precisely, it opens a stateless session when a normal session/transaction is ongoing, and the stateless session uses this same transaction. The stateless session is created with method SessionFactory.openStatelessSession(Connection connection).

I am not able to make this work with Hibernate 5.2. The stateless session is not aware of the ongoing transaction with later Hibernate. Is this some kind of undocumented feature that has been removed / changed? Is there still a way to create a stateless session that would use an already ongoing transaction?


Top
 Profile  
 
 Post subject: Re: Sharing a transaction with multiple sessions
PostPosted: Mon Nov 20, 2017 6:07 am 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1628
Location: Romania
But if you pass the JDBC Connection, it will use the same database transaction.

When you say it does not work, what exactly are you referring to?


Top
 Profile  
 
 Post subject: Re: Sharing a transaction with multiple sessions
PostPosted: Mon Nov 20, 2017 7:34 am 
Newbie

Joined: Wed Nov 18, 2015 10:02 am
Posts: 7
When running the system with Hibernate 5.2, I get "javax.persistence.TransactionRequiredException: Executing an update/delete query" when trying to do something with the stateless session (that was created with SessionFactory.openStatelessSession(Connection connection)).

Not sure if this is related, but with debugger I see that the field currentHibernateTransaction in StatelessSessionImpl is null.


Top
 Profile  
 
 Post subject: Re: Sharing a transaction with multiple sessions
PostPosted: Mon Nov 20, 2017 7:46 am 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1628
Location: Romania
Show us how your data access logic looks like.


Top
 Profile  
 
 Post subject: Re: Sharing a transaction with multiple sessions
PostPosted: Mon Nov 20, 2017 8:34 am 
Newbie

Joined: Wed Nov 18, 2015 10:02 am
Posts: 7
Here's the related code. Classes like HibernateCallback, SessionFactoryUtils and DataSourceUtils are from Spring Framework.

The TransactionRequiredException is thrown whenever I try to use the StatelessSession object in an implementation of method "doInStatelessSession".

Code:
    protected interface StatelessHibernateCallback
    {
        Object doInStatelessSession(StatelessSession sls);
    }

    protected final Object executeStatelessAction(final StatelessHibernateCallback action)
            throws DataAccessException
    {
        return getHibernateTemplate().execute(new HibernateCallback()
            {

                @Override
                public final Object doInHibernate(final Session session) throws HibernateException
                {
                    StatelessSession sls = null;
                    try
                    {
                        sls = this.getStatelessSession();
                        return action.doInStatelessSession(sls);
                    } catch (HibernateException ex)
                    {
                        throw SessionFactoryUtils.convertHibernateAccessException(ex);
                    } finally
                    {
                        if (sls != null)
                        {
                            releaseConnection(sls.connection());
                            sls.close();
                        }
                    }
                }

                private StatelessSession getStatelessSession()
                        throws CannotGetJdbcConnectionException
                {
                    return getSessionFactory().openStatelessSession(getThreadBoundConnection());
                }

                private Connection getThreadBoundConnection()
                        throws CannotGetJdbcConnectionException
                {
                    return DataSourceUtils.getConnection(SessionFactoryUtils
                            .getDataSource(getSessionFactory()));
                }

                private void releaseConnection(Connection connection)
                {
                    DataSourceUtils.releaseConnection(connection,
                            SessionFactoryUtils.getDataSource(getSessionFactory()));
                }
            });
    }


Top
 Profile  
 
 Post subject: Re: Sharing a transaction with multiple sessions
PostPosted: Mon Nov 20, 2017 9:27 am 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1628
Location: Romania
The problem comes from this method:

Code:
private Connection getThreadBoundConnection()
      throws CannotGetJdbcConnectionException
{
   return DataSourceUtils.getConnection(SessionFactoryUtils
         .getDataSource(getSessionFactory()));
}


You are not using the current Session Connection, but a new one.

This is what you should do instead:

Code:
session.doReturningWork(connection -> {
   StatelessSession sls = getSessionFactory()
      .openStatelessSession(connection);
   
   action.doInStatelessSession(sls);
} );


Top
 Profile  
 
 Post subject: Re: Sharing a transaction with multiple sessions
PostPosted: Mon Nov 20, 2017 10:03 am 
Newbie

Joined: Wed Nov 18, 2015 10:02 am
Posts: 7
I changed the code (see below), but I still get the same error.

I also tried calling session.isJoinedToTransaction() before creating the stateless session. It returns true.

Code:
    protected final Object executeStatelessAction(final StatelessHibernateCallback action)
            throws DataAccessException
    {
        return getHibernateTemplate().execute(new HibernateCallback<Object>()
            {
                @Override
                public final Object doInHibernate(final Session session) throws HibernateException
                {
                    return session.doReturningWork(new ReturningWork<Object>()
                        {
                            @Override
                            public Object execute(Connection connection) throws SQLException
                            {
                                StatelessSession sls = null;
                                try
                                {
                                    sls = getSessionFactory().openStatelessSession(connection);
                                    return action.doInStatelessSession(sls);
                                } catch (HibernateException ex)
                                {
                                    throw SessionFactoryUtils.convertHibernateAccessException(ex);
                                }
                            }
                        });
                }
            });
    }


Top
 Profile  
 
 Post subject: Re: Sharing a transaction with multiple sessions
PostPosted: Mon Nov 20, 2017 11:12 am 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1628
Location: Romania
Are you calling this method from a @Transactional Service? Add a breakpoint when the StatelessSession is created and check the stack trace to see if the TranscationInterceptor Spring Aspect is called. If it's not there, then you are not running inside a Transactional method.

Nevertheless, this is a Spring issue, not a Hibernate one since the bootstrapping is done by Spring HibernateTransactionManager or JpaTranscationManager. You need to ask the question on their forum.


Top
 Profile  
 
 Post subject: Re: Sharing a transaction with multiple sessions
PostPosted: Wed Nov 29, 2017 6:56 am 
Newbie

Joined: Wed Nov 18, 2015 10:02 am
Posts: 7
I was finally able to isolate my problem, which seems to be related to native inserts/updates.

The following code works with Hibernate 4.3.11, but fails with TransactionRequiredException on Hibernate 5.2.12:

Code:
           EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory("test");
           SessionFactory sessionFactory = entityManagerFactory.unwrap(SessionFactory.class);   
           Session ses = sessionFactory.openSession();
           Transaction tx = ses.beginTransaction();
          
           ses.doReturningWork(new ReturningWork<Void>() {
   
            @Override
            public Void execute(Connection connection) throws SQLException {
               StatelessSession sls = sessionFactory.openStatelessSession(connection);
               SQLQuery q = sls.createSQLQuery("INSERT INTO testentity (id) values(1)");
               q.executeUpdate();
               return null;
            }
           });


Is this a bug, or just a wrong way to use Hibernate?


Top
 Profile  
 
 Post subject: Re: Sharing a transaction with multiple sessions
PostPosted: Wed Nov 29, 2017 8:27 am 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1628
Location: Romania
Looks like a bug. Write a replicating test case and attach it as an archive to the Jira issue you will create for this problem.


Top
 Profile  
 
 Post subject: Re: Sharing a transaction with multiple sessions
PostPosted: Thu Nov 30, 2017 5:56 am 
Newbie

Joined: Wed Nov 18, 2015 10:02 am
Posts: 7
Jira issue here: https://hibernate.atlassian.net/browse/HHH-12141


Top
 Profile  
 
 Post subject: Re: Sharing a transaction with multiple sessions
PostPosted: Thu Nov 30, 2017 5:58 am 
Hibernate Team
Hibernate Team

Joined: Thu Sep 11, 2014 2:50 am
Posts: 1628
Location: Romania
Thanks


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 12 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.