views:

80

answers:

2

I am doing this in each and every DAL method:

 public static Product GetProductByPartNumber(String partNumber)
    {
         Session session = HibernateUtil.getSessionFactory().getCurrentSession();

         session.beginTransaction();


         Product product = (Product)session.createCriteria(Product.class)
                                    .add(Restrictions.eq("partNumber", partNumber))
                                    .uniqueResult();
         session.getTransaction().commit();



         return product;
    }

This is causing problems, giving me 'session is closed' errors because of lazy loading etc.

How can I have getCurrentSession to not get a new session?

public class HibernateUtil {

    private static final SessionFactory sessionFactory = buildSessionFactory();

    private static SessionFactory buildSessionFactory() {
        try {
            // Create the SessionFactory from hibernate.cfg.xml
            Configuration configuration = new Configuration().configure();

            //configuration.addClass(hsspider.Model.AMCategory.class);

            return configuration.buildSessionFactory();
        }
        catch (Throwable ex) {
            // Make sure you log the exception, as it might be swallowed
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }


}



 <!-- Enable Hibernate's automatic session context management -->
        <property name="current_session_context_class">thread</property>

I am guessing that is the problem, that the call to getCurrentSession is not getting the current session right?

Or does calling transaction.commit(); kill the session? Should I just use flush?

+2  A: 

Did you look at the Transaction javadoc that I'm quoting below?

Allows the application to define units of work, while maintaining abstraction from the underlying transaction implementation (eg. JTA, JDBC).

A transaction is associated with a Session and is usually instantiated by a call to Session.beginTransaction(). A single session might span multiple transactions since the notion of a session (a conversation between the application and the datastore) is of coarser granularity than the notion of a transaction. However, it is intended that there be at most one uncommitted Transaction associated with a particular Session at any time.

And, about Transaction#commit():

Flush the associated Session and end the unit of work (unless we are in FlushMode.NEVER. This method will commit the underlying transaction if and only if the underlying transaction was initiated by this object.

This should answer your question: commit() doesn't kill the session (that can span multiple transaction as we saw).

Another good idea would be to put a breakpoint and to look at the internal details (you may need to tell your IDE where to find Hibernate sources for this).

I also suggest to check Pluggable Session management in Hibernate 3.1 and the more recent Sessions and transactions (especially Transaction demarcation with plain JDBC).

Pascal Thivent
A: 

It could be that you use the ThreadLocalSessionContex. The interesting part of that javadoc is:

it was decided to have this default impl actually generate a session upon first request and then clean it up after the Transaction associated with that session is committed/rolled-back

The best way to deal with this is to move your transaction boundaries to incorporate the entire process; that is, not only getting the Product but also doing whatever you want with it.

You can change the behavior of ThreadLocalSessionContext by subclassing it and re-implementing isAutoCloseEnabled() and other methods. You'd have to find a way to signal closing of the session though.

extraneon
This is not exactly my understanding of http://relation.to/Bloggers/PluggableSessionManagementInHibernate31 and https://www.hibernate.org/42.html.
Pascal Thivent