-->
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.  [ 23 posts ]  Go to page Previous  1, 2
Author Message
 Post subject:
PostPosted: Wed May 10, 2006 11:34 am 
Beginner
Beginner

Joined: Sun Feb 19, 2006 3:50 am
Posts: 34
Oh, by the way, I think you need to use sessionFactory.getCurrentSession() in order to have the new session context control your sessions. Don't use sessionFactory.openSession() or it may not work! I haven't tested to be sure sessionFactory.openSession() doesn't work, but I have a feeling it won't.

Take a look at http://www.hibernate.org/42.html#A9 for more info, specifically the last paragraph of the
"Implementing long Conversations" section. I'm pretty sure this is what led me to the Caveat Emptor code that I posted before.


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 10, 2006 1:39 pm 
Newbie

Joined: Fri Apr 21, 2006 10:49 am
Posts: 18
So, in your filter you don't do any of the biding unbiding, you just commit and execute a flush at the end of the conversation?


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 10, 2006 2:33 pm 
Beginner
Beginner

Joined: Sun Feb 19, 2006 3:50 am
Posts: 34
Binding happens automatically when a new session is opened. I have a convenience method that unbinds and closes the session:

Code:
    public void closeSession()
    {
        Session unboundCurrentSession = ThreadLocalSessionContextNoAutoClose.unbind(sessionFactory);
        if (unboundCurrentSession != null)
            unboundCurrentSession.close();
        else
            logger.warn("In HibernateUtil.closeSession(), and unbind() returned a null session!");
    }


You can bind/unbind at other times if you want.

The bottom line is that by using this custom SessionContext class, you can commit a transaction without persisting changes to the database, even if you session.save(object) a new object. The only way to persist changes to the database is to explicitly flush the session before committing a transaction if you use this custom SessionContext class and sessionFactory.getCurrentSession().

FYI - If you're curious about my open session in view strategy, I'm running Struts with Tiles. At the start of my Action, I open a transaction. At the end of the Action, I flush and commit, which persists my changes to the database. I also built some custom tags that I placed at the beginning and end of my tiles template (so I don't have to do it on every JSP page body, just the template). The tag at the beginning opens a transaction. Since I haven't closed the session yet, any JSP activity that calls hibernate objects will successfully lazy-load. The tag at the end of the tiles template clears the session (I only want database changes to be persisted in my Action classes), commits the transaction (which should do nothing since I cleared the session), and closes the session to release resources. The next Action will then end up getting a new session, and the process repeats. You'll notice I'm not using any servlet filters.

Hope that helps.


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 10, 2006 2:51 pm 
Newbie

Joined: Fri Apr 21, 2006 10:49 am
Posts: 18
ninjapower, I tried the code you posted but I still get the same result, meaning the save gets committed even though is not the end of the conversation (no flush() called).
Thanks for the tip about the articles, but believe me I have read them many times and I have gone through the whole caveatemptor sample.

I used your ThreadLocalSessionContextNoAutoClose.java class.

I also used the following filter

Code:
public class ThreadLocalSessionContextNoAutoCloseFilter implements Filter
{

    private static Log log = LogFactory
            .getLog(ThreadLocalSessionContextNoAutoCloseFilter.class);

    private SessionFactory sf;

    public static final String END_OF_CONVERSATION_FLAG = "end_of_conversation";

    public void doFilter(ServletRequest request, ServletResponse response,
            FilterChain chain) throws IOException, ServletException
    {

        try
        {
            log.debug("Starting a database transaction");
            sf.getCurrentSession().beginTransaction();

            // Do the work...
            chain.doFilter(request, response);

            // End or continue the long-running conversation?
            if (request.getAttribute(END_OF_CONVERSATION_FLAG) != null)
            {

                log.debug("Flushing Session");
                sf.getCurrentSession().flush();

                log.debug("Committing the database transaction");
                sf.getCurrentSession().getTransaction().commit();

                log.debug("<<< End of conversation");

            }
            else
            {

                log.debug("Committing database transaction");
                sf.getCurrentSession().getTransaction();
                sf.getCurrentSession().getTransaction().commit();

                log.debug("> Returning to user in conversation");
            }

        }
        catch (StaleObjectStateException staleEx)
        {
            log
                    .error("This interceptor does not implement optimistic concurrency control!");
            log
                    .error("Your application will not work until you add compensation actions!");
            throw staleEx;
        }
        catch (Throwable ex)
        {
            // Rollback only
            try
            {
                if (sf.getCurrentSession().getTransaction().isActive())
                {
                    log.debug("Trying to rollback database transaction after exception");
                    sf.getCurrentSession().getTransaction().rollback();
                }
            }
            catch (Throwable rbEx)
            {
                log.error("Could not rollback transaction after exception!", rbEx);
            }
            finally
            {
                log.error("Cleanup after exception!");

                // Cleanup
                log.debug("Closing and unbinding Session from thread");
                sf.getCurrentSession().close(); // Unbind is automatic here


            }

            // Let others handle it... maybe another interceptor for exceptions?
            throw new ServletException(ex);
        }

    }

    public void init(FilterConfig filterConfig) throws ServletException
    {
        log
                .debug("Initializing filter, obtaining Hibernate SessionFactory from HibernateUtil");
        sf = HibernateUtil.getSessionFactory();
    }

    public void destroy()
    {
    }

}



and this is the configuration I am using


Code:
        <property name="current_session_context_class">ThreadLocalSessionContextNoAutoClose</property>
             
                   
        <property name="hibernate.transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>
       


as I debug, the insert query in the console shows up right after the save command.

Any details you can think of ninjapower, that I may be missing? (Yes I am using getCurrentSession()


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 10, 2006 3:04 pm 
Newbie

Joined: Fri Apr 21, 2006 10:49 am
Posts: 18
ninjapower, sorry I missed your posting, I think you posted a couple of seconds before I did.
So you are not using a filter. I am going to try to recreate the scenario you are describing managing the transaction from the struts action. I have been going crazy trying to accomplish the lazy loading without using a filter and I really like your idea. Let me create some scenarios.


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 10, 2006 5:14 pm 
Beginner
Beginner

Joined: Sun Feb 19, 2006 3:50 am
Posts: 34
Let me know how it goes. Also, make sure you have auto commit turned off! Otherwise you'll get things committed to the database no matter what else you do. Set <property name="hibernate.connection.autocommit">false</property> in your hibernate properties file.

And rate my post if it's been helpful. =)


Top
 Profile  
 
 Post subject:
PostPosted: Fri May 12, 2006 12:49 pm 
Newbie

Joined: Tue May 02, 2006 6:54 pm
Posts: 10
Location: Salt Lake City, Utah
neketsushonen wrote:
I am sorry, i forgot tell you: the commit() insidely call flush()metod. So your object is always can be saved.

P.D:

The Session is never flushed unless flush() is explicitly called by the application. This mode is very efficient for read only transactions.


What a nonsense! Commit checks for FlushMode.


Top
 Profile  
 
 Post subject: Re: confused about FlushMode.NEVER
PostPosted: Thu Nov 04, 2010 7:58 am 
Pro
Pro

Joined: Mon Apr 16, 2007 8:10 am
Posts: 246
This post would profit by giving some clarification on what exactly a "long conversation" is.

Can it include insert and update statements for example ?

If so, it is different than having a session opened until the view is displayed so as to have access to any not yet loaded lazy collection.

Do we have two different design cases here ?


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 23 posts ]  Go to page Previous  1, 2

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.