Hibernate - Session管理与批量数据处理详解

简介: Hibernate - Session管理与批量数据处理详解

【1】Hibernate管理session

① Hibernate 自身提供了三种管理 Session 对象的方法:


Session 对象的生命周期与本地线程绑定

Session 对象的生命周期与 JTA 事务绑定

Hibernate 委托程序管理 Session 对象的生命周期

在 Hibernate 的配置文件中, hibernate.current_session_context_class 属性用于指定 Session 管理方式, 可选值包括:


thread: Session 对象的生命周期与本地线程绑定

jta*: Session 对象的生命周期与 JTA 事务绑定

managed: Hibernate 委托程序来管理 Session 对象的生命周期


② Session 对象的生命周期与本地线程绑定

如果把 Hibernate 配置文件的 hibernate.current_session_context_class 属性值设为 thread, Hibernate 就会按照与本地线程绑定的方式来管理 Session。

<!-- 配置管理 Session 的方式 -->
<property name="current_session_context_class">thread</property>

Hibernate 按一下规则把 Session 与本地线程绑定

当一个线程(threadA)第一次调用 SessionFactory 对象的 getCurrentSession() 方法时, 该方法会创建一个新的 Session(sessionA) 对象, 把该对象与 threadA 绑定, 并将 sessionA 返回 ;

当 threadA 再次调用 SessionFactory 对象的 getCurrentSession() 方法时, 该方法将返回 sessionA 对象;

当 threadA 提交 sessionA 对象关联的事务时, Hibernate 会自动flush sessionA 对象的缓存, 然后提交事务, 关闭 sessionA 对象。 当 threadA 撤销 sessionA 对象关联的事务时, 也会自动关闭 sessionA 对象。

若 threadA 再次调用 SessionFactory 对象的 getCurrentSession() 方法时, 该方法会又创建一个新的 Session(sessionB) 对象, 把该对象与 threadA 绑定, 并将 sessionB 返回。

【2】批量处理数据

批量处理数据是指在一个事务中处理大量数据。

在应用层进行批量操作, 主要有以下方式:

  • 通过 Session
  • 通过 HQL
  • 通过 StatelessSession
  • 通过 JDBC API(最快)


① 通过session来进行批量操作


Session 的 save() 及 update() 方法都会把处理的对象存放在自己的缓存中。 如果通过一个 Session 对象来处理大量持久化对象, 应该及时从缓存中清空已经处理完毕并且不会再访问的对象。 具体的做法是在处理完一个对象或小批量对象后, 立即调用 flush() 方法刷新缓存, 然后在调用 clear() 方法清空缓存。


通过 Session 来进行处理操作会受到以下约束


需要在 Hibernate 配置文件中设置 JDBC 单次批量处理的数目, 应保证每次向数据库发送的批量的 SQL 语句数目与 batch_size 属性一致;

若对象采用 “identity” 标识符生成器, 则 Hibernate 无法在 JDBC 层进行批量插入操作;

进行批量操作时, 建议关闭 Hibernate 的二级缓存。



批量插入数据:

这种方式性能提升十分有限!

批量更新


在进行批量更新时, 如果一下子把所有对象都加载到 Session 缓存, 然后在缓存中一一更新, 显然是不可取的。


使用可滚动的结果集 org.hibernate.ScrollableResults, 该对象中实际上并不包含任何对象, 只包含用于在线定位记录的游标。只有当程序遍历访问 ScrollableResults 对象的特定元素时, 它才会到数据库中加载相应的对象。


org.hibernate.ScrollableResults 对象由 Query 的 scroll 方法返回:

ScrollableResults  sr = session.createQuery("FROM News").scroll();
int count =0;
while(sr.next()){
  News n = (News)sr.get(0);
  n.setTitle(n.getTitle()+"****");
  if(((count++)+1)%100==0){
    session.flush();
    session.clear();
  }
}


② 通过 HQL 来进行批量操作

HQL 只支持 INSERT INTO … SELECT 形式的插入语句, 但不支持 INSERT INTO … VALUES 形式的插入语句。所以使用 HQL 不能进行批量插入操作。

③ 通过StatelessSession来进行批量操作


从形式上看,StatelessSession与session的用法类似。StatelessSession与session相比,有以下区别:


StatelessSession没有缓存,通过StatelessSession来加载、保存或更新后的对象处于游离状态;

StatelessSession不会与Hibernate的第二级缓存交互;

当调用StatelessSession的save()、update()或delete()方法时,这些方法会立即执行相应的SQL语句,而不会仅计划执行一条SQL语句;

StatelessSession不会进行脏检查,因此修改了Customer对象属性后,还需要调用StatelessSession的update()方法来更新数据库中数据;

StatelessSession不会对关联的对象进行任何级联操作;

通过同一个StatelessSession对象两次加载OID为1的Customer对象,得到的两个对象内存地址不同;

StatelessSession所做的操作可以被Interceptor拦截器捕获到,但是会被Hibernate的事件处理系统忽略掉。


④ 使用JDBC进行批量操作

目录
相关文章
|
3月前
|
缓存 安全 Java
|
3月前
|
缓存 安全 Java
Hibernate 中的 Session 是线程安全的吗?
【8月更文挑战第21天】
43 0
|
3月前
|
缓存 安全 Java
Hibernate 中的 Session 是什么?
【8月更文挑战第21天】
41 0
|
6月前
|
存储 缓存 Java
Hibernate - Session方法与持久化对象详解
Hibernate - Session方法与持久化对象详解
146 0
|
6月前
|
SQL 缓存 Java
Hibernate - SessionFactory和Session详解
Hibernate - SessionFactory和Session详解
124 0
|
SQL Java 数据库连接
Hibernate中的Session对象
Hibernate中的Session对象
89 0
|
关系型数据库 MySQL Java
Could not open Hibernate Session for transaction; nested exception is org.hibernate.TransactionExcep linux下mysql修改连接超时wait_timeout修改后就ok了
Could not open Hibernate Session for transaction; nested exception is org.hibernate.TransactionExcep linux下mysql修改连接超时wait_timeout修改后就ok了
183 1
|
XML 存储 SQL
问:hibernate的sessionfactory是干嘛的?session又是干嘛的呢?
问:hibernate的sessionfactory是干嘛的?session又是干嘛的呢?
98 1
hibernate4 could not initialize proxy - no Session
hibernate4 could not initialize proxy - no Session
|
缓存 Java 数据库连接
Hibernate Session 生命周期|学习笔记
快速学习 Hibernate Session 生命周期
187 0