代码之家  ›  专栏  ›  技术社区  ›  Mahmoud Saleh

关于Hibernate session.flush()的问题

  •  28
  • Mahmoud Saleh  · 技术社区  · 15 年前

    我想询问在以下情况下flush方法的实际功能:

    for (int i = 0; i < myList.size(); i++) {
        Car c = new Car( car.get(i).getId(),car.get(i).getName() );
        getCurrentSession().save(c);
        if (i % 20 == 0)
            getCurrentSession().flush();
    }
    

    有人能向我解释一下情况属实时会发生什么吗。

    4 回复  |  直到 15 年前
        1
  •  53
  •   Pascal Thivent    15 年前

    Session#flush :

    在提交事务之前 flush-mode , Transaction.commit() 调用此方法)。

    冲洗 是同步底层 记忆中的状态。

    换句话说, flush 告诉Hibernate执行将JDBC连接的状态与会话级缓存中保存的对象的状态同步所需的SQL语句。情况如何 if (i % 20 == 0) 会让每一天都成为现实 i 20的倍数。

    Car 实例将保存在会话级缓存中,对于大型 myList.size() ,你会吃掉所有的记忆,最终得到一个 OutOfMemoryException . 为了避免这种情况,文档中描述的模式是 以及 clear

    13.1. Batch inserts

    使新对象持久化时 flush()然后clear()清除会话 为了控制尺寸 一级缓存的。

    Session session = sessionFactory.openSession();
    Transaction tx = session.beginTransaction();
    
    for ( int i=0; i<100000; i++ ) {
        Customer customer = new Customer(.....);
        session.save(customer);
        if ( i % 20 == 0 ) { //20, same as the JDBC batch size
            //flush a batch of inserts and release memory:
            session.flush();
            session.clear();
        }
    }
    
    tx.commit();
    session.close();
    

    另请参见

        2
  •  2
  •   frictionlesspulley sameer    15 年前

    取决于刷新模式的设置方式。

    在默认配置中,Hibernate尝试在三个位置与数据库同步。

    1. before querying data
    2. on commiting a transaction
    3. explictly calling flush
    

    如果 FlushMode 这个 session.flush() 调用将对象实例保存到数据库中。

    session.clear() callacutally可用于清除持久性上下文。

        3
  •  1
  •   Manish Singh    15 年前
    // Assume List to be of 50 
    for (int i = 0; i < 50 ; i++) {
            Car c = new Car( car.get(i).getId(),car.get(i).getName() );
            getCurrentSession().save(c);
        // 20 car Objects which are saved in memory syncronizes with DB 
            if (i % 20 == 0)
                getCurrentSession().flush();
    
    }
    

    关于为什么刷新应该与批大小匹配,没有更多的提示了 要启用批处理,需要设置jdbc批大小

    // In your case 
    hibernate.jdbc.batch_size =20
    

    使用批处理时的一个常见陷阱是,如果您使用的是单个对象更新或插入,那么就可以了

    例如

    // Assume List to be of 50 
        for (int i = 0; i < 50 ; i++) {
                Car c = new Car( car.get(i).getId(),car.get(i).getName() );
            // Adding accessory also in the card here
                Accessories a=new Accessories("I am new one");
                c.add(a);
            // Now you got two entities to be persisted . car and accessory 
            // Two SQL inserts 
                getCurrentSession().save(c);
            // 20 car Objects which are saved in memory syncronizes with DB 
            // Flush here clears the car objects from 1st level JVM cache
                if (i % 20 == 0)
                getCurrentSession().flush();
                        getCurrentSession().clear();
        }
    

    1个用于插入车内 1个用于插入附件

    为了正确配料,你必须设置

    <prop  key="hibernate.order_inserts">true</prop>
    

    对于一个事务下的不同操作,您可以看看 http://docs.jboss.org/hibernate/core/3.2/api/org/hibernate/event/def/AbstractFlushingEventListener.html

        4
  •  0
  •   user333306 user333306    15 年前

    是的,每20个循环,就会为未保存的对象生成和执行sql。您还应该将批处理模式设置为20以提高性能。