-->
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.  [ 6 posts ] 
Author Message
 Post subject: Migrating from hibernate 2.1 to 3.1
PostPosted: Tue Apr 18, 2006 7:04 pm 
Newbie

Joined: Tue Apr 18, 2006 6:43 pm
Posts: 11
Hibernate version: 3.1
Name and version of the database you are using: mysql 4.1

I'm using hibernate session has a singleton with a filter for a webbapp and i've been migrating from 2.1 to 3. Solved most of the problems but im getting a problem with transactions.

I call a transaction begin, do some code and call another method that also calls a begin and a commit (everything in the same session suppostly), so when that method returns and the first (outer) begin commit() is called, the transaction is "!isavailable() ", throwing a "TransactionException("Transaction not successfully started");".

I read the hibernate docs but have no clue from what could it be the problem since for that method class to be independent i should be wrapped in a start() commit() i think. Help?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Apr 18, 2006 7:31 pm 
Beginner
Beginner

Joined: Thu Aug 19, 2004 2:33 pm
Posts: 30
Location: CA, USA
How you are getting the inner Transaction? If it's session.getTransaction().begin(), I think you are actually operating in the same transaction as the outer one. Thus when you commit() that one, it's committing the outer one.

The Session.beginTransaction() javadoc says

Quote:
Begin a unit of work and return the associated Transaction object. If a new underlying transaction is required, begin the transaction. Otherwise continue the new work in the context of the existing underlying transaction. The class of the returned Transaction object is determined by the property hibernate.transaction_factory.


My guess is that you don't want that method to create a new transaction and close it. It should just use the existing transaction and let the outer (wrapping) method commit it.


Top
 Profile  
 
 Post subject: Migrating from hibernate 2.1 to 3.1
PostPosted: Wed Apr 19, 2006 5:47 am 
Newbie

Joined: Tue Apr 18, 2006 6:43 pm
Posts: 11
Thank you for replying.

The classes where this happens are DAO's that access the database through Hibernate and the app in question is a 2.4 webapp.
An HibernateFilter servlet filter starts a session at request start and ends it the the request end (through flter chains)

The outer method from class CategoryDAO starts the session like this:
Code:
public static void OuterUpdate(...) throws Exception

{

   Session session = HSessionFactory.createSession();

   Transaction transaction = session.beginTransaction();
   try {
      ...
      // Calls translationDAO to store a string a return its ID
      category.setNameKey(TranslationDAO.update(category.getNameKey(), name));   
      ...   
                session.saveOrUpdate(category);
      transaction.commit();

   } catch (Exception e) {

      transaction.rollback();

      throw e;

   }   
}


The inner method from class TranslationDAO :
Code:
public static synchronized String update(...) throws Exception

{

   Session session = HSessionFactory.createSession();

   Transaction transaction = session.beginTransaction();
   try {
      ...
      transaction.commit();

   } catch (Exception e) {

      transaction.rollback();

      throw e;

   }
}



The HSessionFactory:

Code:
public class HSessionFactory

{

   public static Session createSession() throws Exception

   {

      return HibernateFilter.getSession();

   }

}


The hibernate filter
Code:
public class HibernateFilter implements Filter {



   public static final String SESSION_FACTORY_KEY = SessionFactory.class

         .getName();



   protected static final String configFilePath = "/hibernate.cfg.xml";



   protected static SessionFactory factory = null;



   protected static ThreadLocal hibernateHolder = new ThreadLocal();



   private static void initFactory() throws ServletException {

      URL configFileURL = HibernateFilter.class

            .getResource(configFilePath);



      if (configFileURL == null)

         throw new ServletException(

               "Hibernate config file not found.");



      try {

         Configuration configuration = new Configuration();

         configuration.configure(configFileURL);



         factory = configuration.buildSessionFactory();

      } catch (Exception e) {

         throw new ServletException(e);

      }

   }



   public void init(FilterConfig filterConfig) throws ServletException {

      /*

       * URL configFileURL =

       * HibernateFilter.class.getResource(configFilePath);

       *

       * if (configFileURL == null) throw new

       * ServletException("Hibernate config file not found.");

       *

       * try { Configuration configuration = new Configuration();

       *

       * configuration.configure(configFileURL);

       *

       * factory = configuration.buildSessionFactory(); } catch

       * (Exception e) { throw new ServletException(e); }

       */

   }



   public void doFilter(ServletRequest request, ServletResponse response,

         FilterChain chain) throws IOException, ServletException {



      if (hibernateHolder.get() != null)

         throw new IllegalStateException(

               "A session is already associated with this thread!  "

                     + "Someone must have called getSession() outside of the context "

                     + "of a servlet request.");



      try {

         chain.doFilter(request, response);

      } finally {

         Session sess = (Session) hibernateHolder.get();

         if (sess != null) {

            hibernateHolder.set(null);



            try {

               sess.close();

            } catch (HibernateException ex) {

               throw new ServletException(ex);

            }

         }

      }

   }



   public static Session getSession() throws Exception {

      Session sess = (Session) hibernateHolder.get();



      if (sess == null) {



         /*

          * if (!HibernateFilter.calledWithinRequest())

          * System.out.println("----------------- mec

          * -----------------");

          */

         synchronized (hibernateHolder) {

            if (factory == null)

               initFactory();

         }



         Runtime.getRuntime().gc();

         sess = factory.openSession();

         hibernateHolder.set(sess);

      }



      return sess;

   }



   public void destroy() {

   }

}


Top
 Profile  
 
 Post subject:
PostPosted: Wed Apr 19, 2006 12:38 pm 
Beginner
Beginner

Joined: Thu Aug 19, 2004 2:33 pm
Posts: 30
Location: CA, USA
I suspect that the inner beginTransaction() is doing nothing since it detects that a transaction is already open. So the inner commit is ending the outer commit as well.

A lot of people using Hibernate and DAOs remove the transaction handling from the DAO layer and do it one level higher. The Open Session In View pattern on the Wiki shows a Servlet Filter implementation that handles the transaction at the fitler level (in the doFilter() method) instead of at the lower DAO level. The nice thing about that is that your DAOs don't have to worry about transactions and you can call as many different DAOs as you want without worrying if the any of the db calls are in separate transactions.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Apr 19, 2006 12:40 pm 
Beginner
Beginner

Joined: Thu Aug 19, 2004 2:33 pm
Posts: 30
Location: CA, USA
With Hibernate 3, you should also look into using SessionFactory.getCurrentSession() instead of using the ThreadLocal that you have in your filter. In Hibernate 2, it was common to use the ThreadLocal, but in Hibernate 3 they added the getCurrentSession() method to handle that for you.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Apr 19, 2006 12:55 pm 
Newbie

Joined: Tue Apr 18, 2006 6:43 pm
Posts: 11
thanks. i read 'open session in view' earlier. Guess i'm gonna have to rewrite all the DAO's .... woohoo :)


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 6 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.