一尘不染

使用StatelessSession进行批处理

hibernate

文档

如果遇到需要插入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();

为什么我们应该使用这种方法?与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();

我的意思是,这个(“替代”)最后一个示例不使用内存,不需要进行同步,清除缓存,那么对于这样的情况,这应该是最佳实践吗?那么为什么要使用前一个呢?


阅读 241

收藏
2020-06-20

共1个答案

一尘不染

从文档中,您链接到:

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

这些是一些重要的限制!

如果您要创建的对象或所做的修改是对单个对象的标量字段的简单更改,那么我认为与批处理常规会话相比,无状态会话没有任何缺点。但是,一旦您想做一些更复杂的操作(例如,操作一个对象或从第一个对象层叠而来的另一个对象的集合值属性),那么无状态会话将比帮助有所障碍。

更一般地,如果批处理的普通会话所提供的性能足够好,那么无状态会话就是不必要的复杂性。它看起来像普通的会话,但是它具有不同的API和不同的语义,这是引发错误的一种方式。

当然,在某些情况下,它是适当的工具,但我认为这些是例外,而不是规则。

2020-06-20