Announcement Announcement Module
Collapse
No announcement yet.
Multiple HibernateTemplate Method Invocations In Single Session Page Title Module
Move Remove Collapse
X
Conversation Detail Module
Collapse
  • Filter
  • Time
  • Show
Clear All
new posts

  • Multiple HibernateTemplate Method Invocations In Single Session

    What is the best way to invoke multiple HibernateTemplate template methods in a single session?

    It seems like HibernateTemplate will open a new session if there's not a current one, do the method operation, then close the session. However, when there are multiple steps required, this isn't so useful.

    For instance, to intialize an object's lazy-fetched collections, we need to re-attach the object, then we can invoke initialize() using the open session; i.e.

    Code:
    public void initialize(Master master) throws DataAcessException {
        Session s = null;
        try {
            s = hibernateTemplate.getSessionFactory().openSession();
            hibernateTemplate.lock(master, LockMode.READ);
            hibernateTemplate.initialize(master.getDetails());
        } finally {
            if (s != null) { s.close(); }
        }
    }
    But that seems to offer little advantage over this:

    Code:
    public void initialize(Master master) throws HibernateException {
        Session s = null;
        try {
            s = this.sessionFactory.openSession();
            s.lock(master, LockMode.READ);
            Hibernate.initialize(master.getDetails());
        } finally {
            if (s != null) { s.close(); }
        }
    }
    I'm not sure I see any benefit of using HibernateTemplate instead of Hibernate directly, especially now that HibernateException is an unchecked exception.

    Maybe I'm missing something and am using HibernateTemplate incorrectly?

    --
    jack

  • #2
    What is the best way to invoke multiple HibernateTemplate template methods in a single session?
    If they're done in the same thread, the session is re-used. Are you using different threads?

    I'm not sure I see any benefit of using HibernateTemplate instead of Hibernate directly, especially now that HibernateException is an unchecked exception
    You still remove boilerplate code (resource acquisition, release, try/catch/finally), and you get the Consistent exception hierarchy.

    Comment


    • #3
      Thanks for responding.

      If they're done in the same thread, the session is re-used. Are you using different threads?
      I remembered that HibernateTemplate instances are thread-safe and took care of opening and closing sessions. Since this is a web app, there will be a different thread-per-request; however, the problems I've been encountering are when I'm the only user, running Tomcat on my local machine, and doing a single request.

      If I write the re-attach and initialize method the following way, I get an exception on the initialize() method call:

      Code:
      public void initialize(Master master) throws DataAcessException {
          hibernateTemplate.lock(master, LockMode.READ);
          hibernateTemplate.initialize(master.getDetails());
      }
      The exception reads:

      disconnected session; nested exception is org.hibernate.HibernateException: disconnected session

      That led me to believe the lock() method opened a sesson, got the lock, then closed the session. Of course, this didn't seem at all useful to me!

      Also, when does the Session get closed when there are HibernateTemplate method calls like shown above?

      In plain vanilla Hibernate, I start a try{} block, get a Session from a SessionFactory, invoke methods on that session, then close the Session in a finally block.

      With the HibernateTemplate, I don't see the same "Begin Work" / "End Work" semantics, so am less sure about when Session are opened/reused and how the HibernateTemplate knows when to close a session.

      I'm missing something here and would appreciate a nudge back onto course.

      TIA!

      --
      jack

      Comment


      • #4
        I just tried the following on a class that extends HibernateDaoSupport which had a SessionFactory injected into it, not a HibernateTemplate instance.

        I was hoping that by getting a session, doing the work, and releasing the session I could ensure the session wasn't disconnected.

        Code:
        public void initialize(Master master) throws DataAcessException {
            Session s = super.getSession();
            hibernateTemplate.lock(master, LockMode.READ);
            hibernateTemplate.initialize(master.getDetails());
            super.releaseSession(s);
        }
        However, I still got the disconnected session exception when the initialize() method was called. Interestingly, this works:

        Code:
        public void initialize(Master master) throws DataAcessException {
            Session s = super.getSession();
            s.lock(master, LockMode.READ);
            Hibernate.initialize(master.getDetails());
            super.releaseSession(s);
        }
        --
        jack

        Comment


        • #5
          Hi jj_jackson!

          Thank you for your message. It gave me a hint how to deal with lazy collection post-loading after processing HQL query.

          Of course, each your call to HibernateTemplate will open a new Hibernate session and close it, so, you attempt to attach an object to a session using lock() call has no effect, as the session is closed afterwards. What you need is to implement HibernateCallback and execute all operations (list() + Hibernate.initialize()) in one hibernate session via getHibernateTemplate().execute().

          Comment


          • #6
            Some years later...

            From the HibernateTemplate docs:
            Furthermore, some operations just make sense within transactions, for example: contains, evict, lock, flush, clear.
            By default HibernateTemplate will use the same existing transaction for all the operations. That means that while in a transaction you can call HibernateTemplate.initialize at any point and it will work. Or HibernateTemplate.lock + HibernateTemplate.initialize if the master record was loaded in a different transaction.

            The way to implement an 'initialize' method that works outside of transactions in a HibernateDaoSupport's subclass is this:
            Code:
            public <E> E initialize(final Object parent, final E proxy) {
            	return getHibernateTemplate().executeWithNativeSession(new HibernateCallback<E>() {
            		public E doInHibernate(Session session) throws HibernateException {
            			session.lock(parent, LockMode.NONE);
            			Hibernate.initialize(proxy);
            			return proxy;
            		}
            	});
            }
            That way you can do this:
            Code:
            List<Order> orders = myDao.getPendingOrders();
            for(Order order: orders) {
            	Set<OrderLines> lines = myDao.initialize(order, order.getOrderLines());
            	if (lines.size() > 0) {
            		Customer c = myDao.initialize(order, order.getCustomer());
            		// Send mail to customer
            		sendPendingNotificationMail(c.getEmail());
            	}
            }

            Comment


            • #7
              Originally posted by jj_jackson View Post
              What is the best way to invoke multiple HibernateTemplate template methods in a single session?
              If you want to keep session opened for for fixed codespan, you may use something like that:

              Code:
              SessionFactoryUtils.initDeferredClose(getHibernateTemplate().getSessionFactory());
               
              try {
                  getHibernateTemplate().doSomething();
                  ...
                  getHibernateTemplate().doAgain();
              }
              finally {
                  SessionFactoryUtils.processDeferredClose(getHibernateTemplate().getSessionFactory());
              }

              Comment

              Working...
              X