简体   繁体   中英

Hibernate PersistenceContext session Flush

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;
        }

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.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM