0
votes

i want to know when does hibernate fulshes the context session when i call session= session.getCurrentSession()

The thing is i have 2 methods in my dao calling getCurrentSession(), when i process the update making the call to getCurrentSession() the entitys are empty:

SessionImpl(PersistenceContext[entityKeys=[],collectionKeys=[]];...)

How can i make this entitys persist from the select method to the update method?

Here are my methods:

public List<SystemConfiguration> getListConfigurations() {
    List<SystemConfiguration> lista = new ArrayList<SystemConfiguration>();
    Session session = null;
    Query query = null;

    String sql = "from SystemConfiguration where description = :desc";
    try {
        /* BEFORE
            session = SessionFactoryUtil.getInstance().getCurrentSession(); 
        @SuppressWarnings("unused")
        Transaction ta = session.beginTransaction(); */
            //FOLLOWING LINE SOLVED THE PROBLEM
            session = SessionFactoryUtil.getInstance().openSession();
        query = session.createQuery(sql);

        query.setString("desc", "configuracion");
        lista = query.list();

        return lista;
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}


public void updateConfigurations(List<SystemConfiguration> configs) throws Exception{
        Session sess = null;
        Transaction tx = null;
        try {
                    //BEFORE
            //sess = SessionFactoryUtil.getInstance().getCurrentSession();
                    //FOLLOWING LINE SOLVED THE PROBLEM
                 sess = SessionFactoryUtil.getInstance().openSession(new SystemConfigurationInterceptor());
            tx = sess.beginTransaction();
            for (SystemConfiguration sys : configs) {
                    sess.update(sys);   
            }
            tx.commit();
        } // try
        catch (Exception e) {
            e.printStackTrace();
            if (tx != null && tx.isActive()) {
                tx.rollback();
            } // if
            throw e;
        } 
    }

And this is my interceptor:

public class SystemConfigurationInterceptor extends EmptyInterceptor {
            private int updates;
        private int creates;
        private int loads;
        public void onDelete(Object entity,
                             Serializable id,
                             Object[] state,
                             String[] propertyNames,
                             Type[] types) {
            // do nothing
        }

        // This method is called when Entity object gets updated.
        public boolean onFlushDirty(Object entity,
                                    Serializable id,
                                    Object[] currentState,
                                    Object[] previousState,
                                    String[] propertyNames,
                                    Type[] types) {

            if ( entity instanceof SystemConfiguration ) {
                updates++;
                for ( int i=0; i < propertyNames.length; i++ ) {
                    if ( "updated_at".equals( propertyNames[i] ) ) {
                        currentState[i] =  new Timestamp(Calendar.getInstance().getTime().getTime());
                        return true;
                    }
                }
            }
            return false;
        }

        public boolean onLoad(Object entity,
                              Serializable id,
                              Object[] state,
                              String[] propertyNames,
                              Type[] types) {
            if ( entity instanceof SystemConfiguration ) {
                loads++;
            }
            return false;
        }

     // This method is called when Entity object gets created.
        public boolean onSave(Object entity,
                              Serializable id,
                              Object[] state,
                              String[] propertyNames,
                              Type[] types) {

            if ( entity instanceof SystemConfiguration ) {
                creates++;
                for ( int i=0; i<propertyNames.length; i++ ) {
                    if ( "updated_at".equals( propertyNames[i] ) ) {
                        state[i] = new Timestamp(Calendar.getInstance().getTime().getTime());
                        return true;
                    }
                }
            }
            return false;
        }

        public void afterTransactionCompletion(Transaction tx) {
            if ( tx.wasCommitted() ) {
                System.out.println("Creations: " + creates + ", Updates: " + updates +", Loads: " + loads);
            }
            updates=0;
            creates=0;
            loads=0;
        }
1
Didn't really understand your question, but using session's default flush mode (AUTO), the session is flushed when: 1) transaction.commit is called 2) A query is being executed - Ori Dar
Is there any way to make the entitys to persist? i mean not to be flushed after a query is executed? - Victor Elizondo
My point is i make a select, it returns a List which then i process it and after that i update it to the DB, my problem is that hibernate is marking all the entitys as dirty because there is nothing in the persistanceContext of the session - Victor Elizondo
I solved it! i dont know why it works but i changed both methods to .openSession() and now everything works fine (the entitys now still in the session it is not auto-flushed), i will update the post with the solution. But now, can someone tell me why openning 2 new sessions make the objects or entitys persist from one to another? - Victor Elizondo

1 Answers

1
votes

Hibernate will flush when you tell it to and when the current transaction is "closed" (usually when the DB connection is returned to the pool somehow).

So the answer to your question depends on which framework you use. With Spring, the session is flushed when the outermost @Transactional method returns.

Your "solution" above will not work for long since it never closes the session. While it returns a result, it will leak a database connection so after a few calls, you will run out of connections.

Also your question doesn't really make sense. SELECT doesn't change objects, so they don't need to be "persisted" before you change them.

After changing them in updateConfigurations(), Hibernate can chose not to write them into the database immediately and just update the cache.

Eventually, if you configured everything correctly, Spring will commit the transaction and that will flush the cache. But when you use Spring, you should never create open and close sessions because it will mess with what Spring is doing.