如果我们有需要插入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();
我的意思是,这个(“替代”)最后一个例子不使用内存,不需要同步,清理缓存,那么这应该是这种情况的最佳实践?为什么要使用之前的?
答案 0 :(得分:10)
从您链接的文档:
特别是,无状态会话不实现第一级缓存,也不与任何第二级或查询缓存交互。它不实现事务性后写或自动脏检查。使用无状态会话执行的操作永远不会级联到关联的实例。无状态会话将忽略集合。通过无状态会话执行的操作绕过Hibernate的事件模型和拦截器。由于缺少第一级缓存,无状态会话容易受到数据别名影响。
这些是一些重大限制!
如果您正在创建的对象或您正在进行的修改是对单个对象的标量字段的简单更改,那么我认为无状态会话与批处理的正常会话相比没有任何缺点。但是,只要你想做一些更复杂的事情 - 操纵一个对象的集合值属性,或者从第一个级联的另一个对象,比如说 - 那么无状态会话更多的是障碍而不是帮助。 / p>
更一般地说,如果批量普通会话提供足够好的性能,那么无状态会话就是不必要的复杂性。它看起来有点像普通会话,但它有不同的API和不同的语义,这就是引发错误的东西。
肯定会有适当的工具,但我认为这些是例外而不是规则。
答案 1 :(得分:1)
无状态会话在性能方面优于Session,因为无状态会话将跳过事务提交到Session对象中使用的会话或会话刷新方法。但是,请务必注意,service / DAO不应尝试对父对象或任何子对象执行会话内数据操作。它会抛出异常。此外,请确保明确关闭会话,否则最终会泄漏连接。
要使用无状态会话获得更高的性能,如果使用Spring驱动的事务,请将Spring事务标记为只读,并将所需的传播设置为从不。
但是,请不要尝试操纵对象模型。
@Transactional(value="someTxnManager", readOnly=true, propagation=Propagation.NEVER)
public List<T> get(...) {
return daoSupport.get(...);
}
在daoSupport中
StatelessSession session = sessionFactory.openStatelessSession();
try{
// do all operations here
}
...
...
finally{
session.close();
}
答案 2 :(得分:-8)
StatelessSession不支持批处理
如果我没有错,我在文档中看到了这一点
StatelessSession未提供的功能和行为
•第一级缓存
•与任何二级或查询缓存的交互
•交易后写或自动脏检查
并使用缓存进行批处理
如果我错了,请原谅我。