Hibernate PersistenceContext会话刷新 [英] Hibernate PersistenceContext session Flush

查看:300
本文介绍了Hibernate PersistenceContext会话刷新的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想知道当我调用session = session.getCurrentSession()时,hibernate何时完成上下文会话?/ p>

事情是我在我的dao调用中有2个方法getCurrentSession(),当我处理更新时调用getCurrentSession()实体为空:

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

如何使这个实体持久化从select方法到更新方法?



以下是我的方法:

  public List< SystemConfiguration> getListConfigurations(){
List< SystemConfiguration> lista = new ArrayList< SystemConfiguration>();
会话会话=空;
查询查询=空;

String sql =from SystemConfiguration where description =:desc;
try {
/ * BEFORE
session = SessionFactoryUtil.getInstance()。getCurrentSession();
@SuppressWarnings(未使用)
交易ta = session.beginTransaction(); * /
//跟随行解决了问题
session = SessionFactoryUtil.getInstance()。openSession();
query = session.createQuery(sql);

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

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



$ b public void updateConfigurations(List< SystemConfiguration> configs)throws Exception {
Session sess = null;
Transaction tx = null;
try {
// BEFORE
// sess = SessionFactoryUtil.getInstance()。getCurrentSession();
//跟随行解决问题
sess = SessionFactoryUtil.getInstance()。openSession(new SystemConfigurationInterceptor());
tx = sess.beginTransaction(); (SystemConfiguration sys:configs){
sess.update(sys);

}
tx.commit();
} //尝试
catch(Exception e){
e.printStackTrace();
if(tx!= null& tx.isActive()){
tx.rollback();
} // if
throw e;


这是我的拦截器:

  public class SystemConfigurationInterceptor extends EmptyInterceptor {
private int updates;
private int创建;
private int加载;
public void onDelete(Object entity,
Serializable id,
Object [] state,
String [] propertyNames,
Type [] types){
//什么都不做
}

//当Entity对象被更新时调用这个方法。
public boolean onFlushDirty(Object entity,
Serializable id,
Object [] currentState,
Object [] previousState,
String [] propertyNames,
Type []类型){

if(System instanceof SystemConfiguration){
updates ++;
for(int i = 0; i< propertyNames.length; i ++){
if(updated_at.equals(propertyNames [i])){
currentState [i] = new时间戳(Calendar.getInstance()的getTime()的getTime());
返回true;
}
}
}
返回false;

$ b $ public boolean onLoad(Object entity,
Serializable id,
Object [] state,
String [] propertyNames,
Type []类型){
if(System instanceof SystemConfiguration){
loading ++;
}
返回false;
}

//当创建实体对象时调用此方法。
public boolean onSave(Object entity,
Serializable id,
Object [] state,
String [] propertyNames,
Type [] types){

if(System instanceof SystemConfiguration){
创建++;
for(int i = 0; i< propertyNames.length; i ++){
if(updated_at.equals(propertyNames [i])){
state [i] = new Timestamp (。Calendar.getInstance()的getTime()的getTime());
返回true;
}
}
}
返回false;
}
$ b $ public void afterTransactionCompletion(Transaction tx){
if(tx.wasCommitted()){
System.out.println(Creations:+ create +,更新:+更新+,加载:+加载);
}
updates = 0;
create = 0;
loads = 0;


解决方案

它在当前事务处于关闭状态时(通常当数据库连接以某种方式返回到池中时)。

因此,您的问题的答案取决于哪个框架你用。在Spring中,当最外层的 @Transactional 方法返回时,会话被刷新。



上面的解决方案不会长时间工作,因为它从不关闭会议。虽然它返回一个结果,它会泄漏一个数据库连接,所以在几次调用之后,你将用完连接。



另外你的问题没有意义。 SELECT 不会更改对象,因此在更改它们之前不需要保留。



updateConfigurations()中更改它们之后,Hibernate可以选择不立即将它们写入数据库并更新缓存。


$ b $最终,如果你正确地配置了一切,Spring将提交事务,并且将刷新缓存。但是当你使用Spring的时候,你永远都不应该创建开闭会话,因为它会混淆Spring正在做的事情。


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.

这篇关于Hibernate PersistenceContext会话刷新的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆