使用StatelessSession进行批处理

ses*_*ses 17 hibernate batch-processing

文档

如果我们有一个需要插入1000 000行/对象的情况:

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();
Run Code Online (Sandbox Code Playgroud)

为什么我们应该使用这种方法?与StatelessSession相比,它给我们带来了什么样的好处:

    StatelessSession session = sessionFactory.openStatelessSession();
    Transaction tx = session.beginTransaction();

    for ( int i=0; i<100000; i++ ) {
      Customer customer = new Customer(.....);
      session.insert(customer);
    }    

    tx.commit();
    session.close();
Run Code Online (Sandbox Code Playgroud)

我的意思是,这个("替代")最后一个例子不使用内存,不需要同步,清理缓存,那么这应该是这样的情况的最佳实践?为什么要使用之前的?

Tom*_*son 10

从您链接到的文档:

特别是,无状态会话不实现第一级缓存,也不与任何第二级或查询缓存交互.它不实现事务性后写或自动脏检查.使用无状态会话执行的操作永远不会级联到关联的实例.无状态会话将忽略集合.通过无状态会话执行的操作绕过Hibernate的事件模型和拦截器.由于缺少第一级缓存,无状态会话容易受到数据别名影响.

这些是一些重大的限制!

如果您正在创建的对象或您正在进行的修改是对单个对象的标量字段的简单更改,那么我认为无状态会话与批处理的正常会话相比没有任何缺点.但是,只要你想做一些更复杂的事情 - 操纵一个对象的集合值属性,或者从第一个级联的另一个对象,比如说 - 那么无状态会话更多的是障碍而不是帮助.

更一般地说,如果批量普通会话提供足够好的性能,那么无状态会话就是不必要的复杂性.它看起来有点像普通会话,但它有不同的API和不同的语义,这是一种引发错误的东西.

肯定会有适当的工具,但我认为这些是例外,而不是规则.

  • 但是为什么我需要一级缓存,如果我在一秒钟内插入10000条记录,然后非常清理这个缓存,我想,没有人有机会使用它,因为那个短暂的时刻?我想它需要一些很好的例子才能理解它......简而言之,正如我所理解的那样:无状态会话对于最简单的情况是好的,因为不需要保存复杂的对象. (3认同)
  • 另外,我找到了一些解释来证明你的观点:http://javainnovations.blogspot.ca/2008/07/batch-insertion-in-hibernate.html (2认同)