-->
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 1, 2  Next
Author Message
 Post subject: confused about FlushMode.NEVER
PostPosted: Thu Apr 27, 2006 3:42 pm 
Newbie

Joined: Fri Apr 21, 2006 10:49 am
Posts: 18
Hibernate Version: Hibernate 3.1 rc3
JDK: 1.4.2
AppServer: Websphere 5.1
Database: DB2 V8

I am running a simple save to the database.
Once I get the session I set it up to FlushMode.NEVER

If I understand correctly what FlushMode.NEVER is suppose to do
"The Session is never flushed unless flush() is explicitly called by the application"
my Employee object objEmployee should not be saved since it was never explicitly flush().
But that is not what I see. my object gets saved into the database. It is like setting or
not setting the session's flush mode to NEVER does not affect the behaviour.

I looked also at the debugging statements. This is what I get witout setting the flushmode. It
makes sense to me.


Code:
14:57:06,261  INFO SettingsFactory:125 - Automatic flush during beforeCompletion(): disabled
14:57:06,261  INFO SettingsFactory:129 - Automatic session close at end of transaction: disabled
14:57:06,267  INFO SettingsFactory:144 - Scrollable result sets: enabled

14:57:07,615 DEBUG AbstractBatcher:470 - closing statement
14:57:07,624 DEBUG JDBCTransaction:103 - commit
14:57:07,624 DEBUG SessionImpl:343 - automatically flushing session
14:57:07,625 DEBUG AbstractFlushingEventListener:58 - flushing session
14:57:07,628 DEBUG AbstractFlushingEventListener:111 - processing flush-time cascades
14:57:07,631 DEBUG AbstractFlushingEventListener:153 - dirty checking collections
14:57:07,631 DEBUG AbstractFlushingEventListener:170 - Flushing entities and processing referenced collections
14:57:07,642 DEBUG AbstractFlushingEventListener:209 - Processing unreferenced collections
14:57:07,643 DEBUG AbstractFlushingEventListener:223 - Scheduling collection removes/(re)creates/updates
14:57:07,643 DEBUG AbstractFlushingEventListener:85 - Flushed: 0 insertions, 0 updates, 0 deletions to 1 objects
14:57:07,644 DEBUG AbstractFlushingEventListener:91 - Flushed: 0 (re)creations, 0 updates, 0 removals to 0 collections
14:57:07,647 DEBUG Printer:83 - listing entities:
14:57:07,648 DEBUG Printer:90 - edu.miami.it.employee.Employee{value1=10431, value2=2006, id=79}
14:57:07,648 DEBUG AbstractFlushingEventListener:289 - executing flush
14:57:07,649 DEBUG AbstractFlushingEventListener:316 - post flush
14:57:07,649 DEBUG JDBCContext:195 - before transaction completion
14:57:07,649 DEBUG SessionImpl:391 - before transaction completion
14:57:07,651 DEBUG JDBCTransaction:193 - re-enabling autocommit
14:57:07,651 DEBUG JDBCTransaction:116 - committed JDBC Connection
14:57:07,652 DEBUG JDBCContext:209 - after transaction completion
14:57:07,652 DEBUG ConnectionManager:285 - aggressively releasing JDBC connection
14:57:07,653 DEBUG ConnectionManager:322 - closing JDBC connection [ (open PreparedStatements: 0, globally: 0) (open ResultSets: 0, globally: 0)]
14:57:07,656 DEBUG SessionImpl:421 - after transaction completion
14:57:07,657 DEBUG SessionImpl:289 - closing session
14:57:07,657 DEBUG ConnectionManager:256 - connection already null in cleanup : no action
14:57:07,658  INFO SessionFactoryImpl:727 - closing


The debugging when I set FlushMode.NEVER is different.


Code:
15:18:32,432  INFO TransactionManagerLookupFactory:42 - instantiated TransactionManagerLookup
15:18:32,432  INFO SettingsFactory:125 - Automatic flush during beforeCompletion(): disabled
15:18:32,432  INFO SettingsFactory:129 - Automatic session close at end of transaction: disabled

15:18:33,507 DEBUG JDBCContext:164 - no active transaction, could not register Synchronization
15:18:33,507 DEBUG SessionImpl:269 - opened session at timestamp: 4694693942976512
15:18:33,508 DEBUG SessionImpl:1138 - setting flush mode to: NEVER
15:18:33,511 DEBUG JDBCTransaction:54 - begin
15:18:33,512 DEBUG ConnectionManager:302 - opening JDBC connection
15:18:33,512 DEBUG JDBCContext:164 - no active transaction, could not register Synchronization
15:18:33,512 DEBUG JDBCTransaction:59 - current autocommit status: true
15:18:33,513 DEBUG JDBCTransaction:62 - disabling autocommit
15:18:33,514 DEBUG JDBCContext:204 - after transaction begin
15:18:33,526 DEBUG DefaultSaveOrUpdateEventListener:161 - saving transient instance
15:18:33,543 DEBUG AbstractSaveEventListener:139 - saving [edu.miami.it.employee.Employee#<null>]
15:18:33,544 DEBUG AbstractSaveEventListener:221 - executing insertions
15:18:33,589 DEBUG AbstractEntityPersister:1940 - Inserting entity: edu.miami.it.employee.Employee (native id)


15:18:33,599 DEBUG IdentifierGeneratorFactory:37 - Natively generated identity: 80
15:18:33,599 DEBUG AbstractBatcher:319 - about to close PreparedStatement (open PreparedStatements: 1, globally: 1)
15:18:33,600 DEBUG AbstractBatcher:470 - closing statement
15:18:33,666 DEBUG JDBCTransaction:103 - commit
15:18:33,667 DEBUG JDBCContext:195 - before transaction completion
15:18:33,667 DEBUG SessionImpl:391 - before transaction completion
15:18:33,672 DEBUG JDBCTransaction:193 - re-enabling autocommit
15:18:33,672 DEBUG JDBCTransaction:116 - committed JDBC Connection



So even the debug statements are quite different they still both save the object.
Can somebody explain why flush mode NEVER does not work?

Here it is my hibernate configuration and the code I am using to save the object



My hibernate configuration is as follows:
Code:

<hibernate-configuration>
    <session-factory >

      <!-- datasource connection properties -->
      <property name="connection.datasource">jdbc/DB2DevlDs</property>   
      
      <!-- dialect for DB2 -->
      <property name="dialect">org.hibernate.dialect.DB2Dialect</property>
       
              <property name="hibernate.show_sql">true</property>
   
              <property name="hibernate.transaction.manager_lookup_class">org.hibernate.transaction.WebSphereTransactionManagerLookup</property>
       
       
              <mapping resource="edu/miami/it/employee/Employee.hbm.xml" />
       
       
    </session-factory>
</hibernate-configuration>



The code I am running is the following:
Code:

        Session session = null;
        Transaction tx = null;
        SessionFactory sessionFactory = null;
        try
        {
            Configuration configuration = new Configuration();
            // Configure from hibernate.cfg.xml at root of classpath.
            configuration.configure();
            sessionFactory = configuration.buildSessionFactory();
            session = sessionFactory.openSession();
            session.setFlushMode(FlushMode.NEVER);
            tx = session.beginTransaction();

            // Save object.
           
            Employee objEmployee2 = new Employee();
            objEmployee2.setValue1(new Integer(10431));
            objEmployee2.setValue2(new Integer(2006));
            session.save(objEmployee2);
           
            tx.commit();
           
            System.out.println("Employee saved!");
        }
        catch (HibernateException e)
        {
            try
            {
                if (tx != null)
                {
                    tx.rollback();
                }
            }
            catch (HibernateException ignore)
            {
                // ignore
            }
            throw e;
        }
        finally
        {
            if (session != null)
            {
                try
                {
                    session.close();
                }
                catch (HibernateException ignore)
                {
                    // ignore
                }
            }
            if (sessionFactory != null)
            {
                try
                {
                    sessionFactory.close();
                }
                catch (HibernateException e)
                {
                    // ignore
                }
            }
        }




Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 27, 2006 4:44 pm 
Regular
Regular

Joined: Wed Feb 22, 2006 11:28 am
Posts: 65
Location: Santiago, Chile
In Hibernate API Documentation, you can see:

FlushMode: Represents a flushing strategy. The flush process synchronizes database state with session state by detecting state changes and executing SQL statements.

ALWAYS
The Session is flushed before every query.

AUTO
The Session is sometimes flushed before query execution in order to ensure that queries never return stale state.

COMMIT
The Session is flushed when Transaction.commit() is called.

NEVER
The Session is never flushed unless flush() is explicitly called by the [u]application.[/u]


So, your application will talk to Hibernate : "hey... save... are you ok?"

requests for your comments


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 27, 2006 5:03 pm 
Newbie

Joined: Fri Apr 21, 2006 10:49 am
Posts: 18
>> So, your application will talk to Hibernate : "hey... save... are you ok?"

I am sorry but I dont understand what you mean by "hey... save... are you ok?"

Yes, with NEVER The Session is never flushed unless flush() is explicitly called by the application., so why is it that if I set session.setFlushMode(FlushMode.NEVER) to never and I do not call flush() the object gets saved on commit if the data from the session was never flushed into the database.
If it is true that : "The flush process synchronizes database state with session state by detecting state changes and executing SQL statements" and flush is never executed do to the fact that flush is set to NEVER and I never call flush() explicitly I do not understand my object got save to the database.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 27, 2006 5:13 pm 
Regular
Regular

Joined: Wed Feb 22, 2006 11:28 am
Posts: 65
Location: Santiago, Chile
Hello Friend:

NEVER
The Session is never flushed unless flush() is explicitly called by the [u]application.[/u]

that meant, your application will coordina when send a sentence to your DataBase. That doesn´t mean your session have no send the sentence for ever. It is manipulated by Application context.

requests for comments.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Apr 27, 2006 5:14 pm 
Regular
Regular

Joined: Wed Feb 22, 2006 11:28 am
Posts: 65
Location: Santiago, Chile
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.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 28, 2006 6:57 am 
Newbie

Joined: Wed Apr 26, 2006 5:21 am
Posts: 14
HI!

I guess, you are using native ID generation, right?

In this case, Hibernate HAS to flush immediately when saving a new object.

Thomas


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 28, 2006 8:35 am 
Newbie

Joined: Fri Apr 21, 2006 10:49 am
Posts: 18
> NEVER
> The Session is never flushed unless flush() is explicitly called by the application.

> that meant, your application will coordina when send a sentence to your DataBase. That > > doesn´t mean your session have no send the sentence for ever. It is manipulated by > > >Application context.

I am not sure if you have look at my code that I put in the initial posting. My application NEVER calls flush(), or at least my code does not explicitly call flush().

> I am sorry, i forgot tell you: the commit() insidely call flush()metod. So your object is > >always can be saved.
This makes a little more sense to me, but if that was the case what is the purpose to have FlushMode.COMMIT, where the flush() will be called on commit().?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 28, 2006 8:41 am 
Newbie

Joined: Fri Apr 21, 2006 10:49 am
Posts: 18
>I guess, you are using native ID generation, right?
>In this case, Hibernate HAS to flush immediately when saving a new object.

Thanks Thomas for the comment. Yes, I am using native ID generation. I tried to test what you said but I am not able to use any other generator, my connection pool errors out if I set it to assigned or sequence or increment.
If you are right, the session-per-conversation pattern where one of the driving forces is the FlushMode.NEVER will not work when I have generators native for my objects?


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 28, 2006 9:32 am 
Beginner
Beginner

Joined: Fri Apr 28, 2006 3:04 am
Posts: 22
Location: Amsterdam
Native generation means your database is responsible for generating the key.
Hibernate needs a identifier when you save your object in hibernate to put in your session. So hibernate has to commit your save to the db to get the identier...
You have to think about transaction within a session, autoflushing enabled.. Do all your queries whithin your transaction and commit it at the end. If any exception occurs within code in your transaction then you should rollback the entire transaction and the first save you did will not be seen in your database.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 28, 2006 10:08 am 
Newbie

Joined: Fri Apr 21, 2006 10:49 am
Posts: 18
Yes Marcelpance, I do agree in everything you mention, but that is the easy scenario in which no need to set flushmode to NEVER. Everything runs within a single transaction and you commit or roll back at the end.

My whole question about flush mode NEVER is trying to understand the session-per-conversation pattern. It is briefly explained in 11.3.2. Extended session and automatic versioning of the Hibernate documentation and implemented in HibernateThreadExtendedFilter class of the lattest caveatemptorHi sample program.
The way I see it they have to do a commit on each request so that they don't keep a handle on resources but they only explicitly flush at the end of the conversation ( a flag will mark the end of the conversation). In the intermediate requests the flush never occurs because the flushmode has been set up to NEVER.
But again in the code I posted, I try to manipulate the flush mode to obtain a similar behaviour as session-per-conversation. I would expect my object not to be perssited to the database since I never call flush() explicitly and the mode is NEVER. Unfortunatelly my object gets saved which throws out the window all my theories about how the flushmode NEVER works.

I like Thomas posting but again, if that was the case the flushmode NEVER has very little use since I believe the most extended way to do generation is native.


Top
 Profile  
 
 Post subject:
PostPosted: Fri Apr 28, 2006 10:17 am 
Beginner
Beginner

Joined: Fri Apr 28, 2006 3:04 am
Posts: 22
Location: Amsterdam
I'm using flashMode.NEVER myself and it is very usefull. Im having a web application with a MVC Controller (Spring) which uses and openSessionInView. Which means i have access to the session as soon as the request gets to my controller. Then it goes up to a manager call..
All manager calls get intercepted by the transaction manager which starts a transaction with the scope of the manager call. Now i handle my business methods and close the transaction (or rollback at exception). But i keep my session open untill all the way back to the JSP. This way i can still use my LazyLoading Sets in my JSP.. I don't want any changes made to my objects in JSP to be saved (which FlushMode.AUTO will do!). So i have to use NEVER.

So there is a use of flushMode never. but im not familiar with the session-per-conversation pattern, so i'm not sure what you are trying to achieve.


Top
 Profile  
 
 Post subject:
PostPosted: Tue May 02, 2006 2:30 pm 
Newbie

Joined: Fri Apr 21, 2006 10:49 am
Posts: 18
OK Marcelpanse, thanks a lot for your response. Unfortunatelly I am not using Spring, but you hit the nail in the head with what I would like to accomplish. That is the exact behaviour that I would like to have. For that, if I use sessionFacade.getCurrentSession(), once I commit the transaction the session is closed and I don't have LazyLoading on the JSP (which ofcourse I would like to have).

I have been experimenting more with FlushMode.NEVER and as long as you dont make an insert of a new object there is no flush to the database, but if you do an insert it flushes immediately as tboerkel said.

Thanks


Top
 Profile  
 
 Post subject: Is Flush Atomic?
PostPosted: Tue May 09, 2006 6:26 pm 
Regular
Regular

Joined: Fri Jul 29, 2005 9:46 am
Posts: 101
But... if you use Flush.Never when you finally call "session.Flush" all the changes that haven't been saved and are finally sent to the database... are sent in a transactional way? is the flush atomic?


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 10, 2006 8:32 am 
Newbie

Joined: Fri Apr 21, 2006 10:49 am
Posts: 18
Yes luxspes you are right, and everything is fine as long as the session is per request.
Now lets take the case of sessions for long conversations http://www.hibernate.org/43.html#A9. When reading this article you get the idea that you can matain a session through different requests and if something goes wrong you will be able to rollback (by using flusmode NEVER). This is the case as long as you dont perform an insert, but if you perform an insert it will get committed in that same request because it has been flushed, therefore it can not be rolled back in the long conversation if something goes wrong on subsequent requests belonging to the same conversation.
I may be missing something but I find the pattern missleading and not very useful, because the chances of having to insert a new row in a long conversation are high, or at least it is for me :)


Top
 Profile  
 
 Post subject:
PostPosted: Wed May 10, 2006 10:48 am 
Beginner
Beginner

Joined: Sun Feb 19, 2006 3:50 am
Posts: 34
It is possible to do what you want fiallega, but you have to do more than simply set the flush mode to never on the session. I'm doing the open session in view pattern, and after a lot of digging around figured out what to do. I got most of this code from the Caveat Emptor program, BTW, and cleaned it up a little for my own purposes:

Code:
import org.hibernate.FlushMode;
import org.hibernate.SessionFactory;
import org.hibernate.classic.Session;
import org.hibernate.context.ThreadLocalSessionContext;
import org.hibernate.engine.SessionFactoryImplementor;

/**
* Extends {@link ThreadLocalSessionContext} to allow for long conversations. It achieves this by setting every
* <code>Session</code> it produces to <code>FlushMode.NEVER</code> so that it won't flush unless explicitly asked
* to, and by preventing the session from auto-closing or unbinding from the thread after a <code>Transaction</code>
* commit. Note that this means the application code must do these functions manually as needed!
*/
public class ThreadLocalSessionContextNoAutoClose extends ThreadLocalSessionContext
{
    /**
     * Create a new instance.
     *
     * @param factory The <code>SessionFactoryImplementor</code> required by the super constructor.
     */
    public ThreadLocalSessionContextNoAutoClose(SessionFactoryImplementor factory)
    {
        super(factory);
    }

    /**
     * Returns <code>false</code> to prevent auto closing.
     *
     * @return <code>false</code> to prevent auto closing.
     */
    protected boolean isAutoCloseEnabled()
    {
        return false;
    }

    /**
     * Returns <code>false</code> to prevent auto flushing.
     *
     * @return <code>false</code> to prevent auto flushing.
     */
    protected boolean isAutoFlushEnabled()
    {
        return false;
    }

    /**
     * Uses <code>super.buildOrObtainSession()</code>, then sets the resulting <code>Session</code>'s flush mode
     * to <code>FlushMode.NEVER</code> to prevent auto-flushing.
     *
     * @return A session configured with <code>FlushMode.NEVER</code>.
     */
    protected Session buildOrObtainSession()
    {
        Session s = super.buildOrObtainSession();
        s.setFlushMode(FlushMode.NEVER);
        return s;
    }

    /**
     * Returns an instance of <code>CleanupSynch</code> which prevents auto closing and unbinding.
     *
     * @return A <code>CleanupSynch</code> which prevents auto closing and unbinding.
     */
    protected CleanupSynch buildCleanupSynch()
    {
        return new NoCleanupSynch(factory);
    }

    /**
     * A simple extension of <code>CleanupSynch</code> that prevents any cleanup from happening. No session closing or
     * unbinding.
     */
    private static class NoCleanupSynch extends ThreadLocalSessionContext.CleanupSynch
    {
        /**
         * Creates a new instance based on the given factory.
         *
         * @param factory The required <code>SessionFactory</code> that is passed to the super constructor.
         */
        public NoCleanupSynch(SessionFactory factory)
        {
            super(factory);
        }

        /**
         * Does nothing, thus helping to prevent session closing and/or unbinding.
         */
        public void beforeCompletion()
        {
            // do nothing
        }

        /**
         * Does nothing, thus helping to prevent session closing and/or unbinding.
         *
         * @param i
         */
        public void afterCompletion(int i)
        {
            // do nothing
        }
    }
}


You use this as your session context class by setting this property in your hibernate properties:
Code:
<property name="hibernate.current_session_context_class">com.my.package.ThreadLocalSessionContextNoAutoClose</property>


Try that and see if it works for you. I tested in my project, and I can start a transaction, create a new object, session.save(object) on it, and close the transaction, and none of my changes are persisted to the database. If I flush before committing the transaction, the changes are persisted. Hope that helps (rate this post if it does please!)


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 1, 2  Next

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.