使用JPA和Hibernate进行批量处理的最佳方式
Tips
原文作者:Vlad Mihalcea
原文地址:The best way to do batch processing with JPA and Hibernate
在本文中,你将了解什么是批处理,为什么要使用它,以及如何在JPA和Hibernate中正确使用它。
批处理
在编写企业应用程序时,通常将工作分配在服务于典型OLTP(在线事务处理)传输的前端系统,和一个或多个批处理用于ETL(Extract,Transform,Load)操作。
批处理器,顾名思义,将要处理的数据分成几个块,因此具有以下优点:
- 每个块可以通过单独的工作线程进行处理,因此增加了吞吐量并减少了整个处理时间。
- 每个块都可以使用自己的数据库事务,所以如果有一个失败,就不用丢掉我们所做的所有工作,只是针对当前事务的变化。
JPA 批处理
当使用JPA时,假设要插入50个Post
实体,那么应该这样做:
int entityCount = 50;
int batchSize = 25;
EntityManager entityManager = null;
EntityTransaction transaction = null;
try {
entityManager = entityManagerFactory()
.createEntityManager();
transaction = entityManager.getTransaction();
transaction.begin();
for ( int i = 0; i < entityCount; ++i ) {
if ( i > 0 && i % batchSize == 0 ) {
entityManager.flush();
entityManager.clear();
transaction.commit();
transaction.begin();
}
Post post = new Post(
String.format( "Post %d", i + 1 )
);
entityManager.persist( post );
}
transaction.commit();
} catch (RuntimeException e) {
if ( transaction != null &&
transaction.isActive()) {
transaction.rollback();
}
throw e;
} finally {
if (entityManager != null) {
entityManager.close();
}
}
每个开始操作都会开启事务,因为每个实体状态转换必须在数据库事务的范围内执行。
for循环一次会持久化一个Post
实体。 但是,由于实体状态转换仅在执行flush
方法更新数据库时执行,因此我们可以将多个SQL 插入语句分组到到要给单一PreparedStatement
执行中,该执行需要多个参数。
每次迭代计数器(变量i)已达到batchSize
临界值的倍数,我们可以刷新EntityManager
并提交数据库事务。 通过在每次批处理执行后提交数据库事务,我们获得以下优点:
- 避免了长期运行的事务,这对MVCC关系数据库系统是不利的。
- 我们确保如果执行失败,不会丢失以前成功执行的批处理作业完成的工作。
EntityManager
在每次批量执行后被清除,这样就不会继续累积可能导致管理实体的几个问题:
- 如果要持久化的实体数量庞大,那么存在内存不足的风险。
- 在持久化上下文中累积的实体越多,flush越慢。 所以,最好的做法是确保持久性上下文尽可能的短小。
如果抛出异常,我们必须确保回滚当前正在运行的数据库事务。 否则可能会导致许多问题,因为数据库可能仍然认为事务处于打开状态,锁可能会被持有,直到事务超时或由DBA结束。
最后,我们需要关闭EntityManager
,以便可以清除上下文并释放Session
级的资源。
虽然这是使用JPA进行批处理的正确方法,但还没有完成。 如前所述,也可以从JDBC批量更新中受益。 为此,我们需要提供以下Hibernate配置属性:
<property
name="hibernate.jdbc.batch_size"
value="25"
/>
<property
name="hibernate.order_inserts"
value="true"
/>
<property
name="hibernate.order_updates"
value="true"
/>
这些属性允许我们将多个SQL语句批处理为单个PreparedStatement
执行,这需要单个数据库往返。 选择值25以匹配EntityManager
批处理作业的临界值。
执行以前的测试用例时,Hibernate生成2个SQL INSERT语句:
INSERT INTO post (title, id) values (?, ?)"],
Params:[
(Post 1, 1), (Post 2, 2), (Post 3, 3),
(Post 4, 4), (Post 5, 5), (Post 6, 6),
(Post 7, 7), (Post 8, 8), (Post 9, 9),
(Post 10, 10), (Post 11, 11), (Post 12, 12),
(Post 13, 13), (Post 14, 14), (Post 15, 15),
(Post 16, 16), (Post 17, 17), (Post 18, 18),
(Post 19, 19), (Post 20, 20), (Post 21, 21),
(Post 22, 22), (Post 23, 23), (Post 24, 24),
(Post 25, 25)
]
INSERT INTO post (title, id) values (?, ?)"],
Params:[
(Post 26, 26), (Post 27, 27), (Post 28, 28),
(Post 29, 29), (Post 30, 30), (Post 31, 31),
(Post 32, 32), (Post 33, 33), (Post 34, 34),
(Post 35, 35), (Post 36, 36), (Post 37, 37),
(Post 38, 38), (Post 39, 39), (Post 40, 40),
(Post 41, 41), (Post 42, 42), (Post 43, 43),
(Post 44, 44), (Post 45, 45), (Post 46, 46),
(Post 47, 47), (Post 48, 48), (Post 49, 49),
(Post 50, 50)
]
结论
了解如何正确设计批处理作业在开发企业应用程序时非常重要。 幸运的是,使用JPA和Hibernate,这个任务很容易实现。 最重要的方面是考虑到如何让关系数据库工作效果最好,这就是驱动数据访问设计决策的因素。
使用JPA和Hibernate进行批量处理的最佳方式的更多相关文章
- JPA入门例子(采用JPA的hibernate实现版本) 转
JPA入门例子(采用JPA的hibernate实现版本) jpahibernate数据库jdbcjava框架(1).JPA介绍: JPA全称为Java Persistence API ,Java持久化 ...
- JPA和Hibernate的相关使用技巧
介绍 尽管有SQL标准,但每个关系数据库终将是唯一的,因此你需要调整数据访问层,以便充分利用在使用中的关系数据库. 在本文中,我们将介绍在使用带有JPA和Hibernate的MySQL时,为了提高性能 ...
- JPA入门例子(采用JPA的hibernate实现版本) --- 会伴随 配置文件:persistence.xml
JPA入门例子(采用JPA的hibernate实现版本) 分类: j2se2011-03-30 16:09 45838人阅读 评论(9) 收藏 举报 jpahibernate数据库jdbcjava框架 ...
- Hibernate的批量插入(&&JDBC)
来自: http://blog.csdn.net/an_2016/article/details/51759890 一.批量插入(两种方式) 1,通过hibernate缓存 如果这样写代码进行批量插入 ...
- JPA和hibernate的关系
实际上,JPA的标准的定制是hibernate作者参与定制的,所以JPA是hibernate的一个总成,可以这么理解
- JPA与Hibernate的关系
1.JPA JPA全称: Java Persistence API JPA通过JDK 5.0注解或XML描述对象-关系表的映射关系,并将运行期的实体对象持久化到数据库中. JPA的出现? JPA ...
- JPA和Hibernate的区别
JPA Java Persistence API,是Java EE 5的标准ORM接口,也是ejb3规范的一部分. Hibernate,当今很流行的ORM框架,是JPA的一个实现,但是其功能是JPA的 ...
- java(样品集成框架spring、spring mvc、spring data jpa、hibernate)
这是你自己的参考springside集成框架的开源项目.主要的整合spring.spring mvc.spring data jpa.hibernate几个框架,对于这些框架中仍然感觉更舒适sprin ...
- 谈论Hibernate级联删除——JPA根据Hibernate实现许多级联删除CascadeType.DELETE_ORPHAN
声明: 1.这篇文章是原创.非复制或转载过来. 2.在本文中,参数都亲自做过实验证明. 3.这篇文章谈到了Hibernate配置基于注释的方法.hbm语法不可用. 不清JPA.Hibernate.EJ ...
随机推荐
- Omi树组件omi-tree编写指南
Omi框架能够以少量的代码声明式地编写可拖拽移动节点的树形组件. 通常树组件能够考验UI框架的健壮性,因为需要使用到UI框架的如下特性: 组件嵌套 组件传值 组件批量传值 组件依赖自身递归嵌套(nes ...
- selenium+python
最近在学习selenium自动化测试,但是一直遇到一个问题,总是打不开指定的网址,今天突然成功了, 主要原因是因为selenium版本太低的缘故,所以只需要在终端输入:pip install -U s ...
- OC中NSFileManager
NSFileManager介绍 NSFileManager是用来管理文件系统的 它可以用来进行常见的文件\文件夹操作(拷贝.剪切.创建等) NSFileManager使用了单例模式singleton ...
- MapControl Application 添加自定义的工具条
现在想用二次开发做一些东西,然后需要自定义的工具条,但是如何向MapControl Application 添加自定义的工具条呢,经过多次试验后,终于找到了相应的方法(左图是添加自定义的工具条之前,右 ...
- Struts2之2.5.10.1HelloWorld
Struts2.5.10.1是目前为止最新的版本,struts2建议持续跟进,理由大家都懂.好了,下面步入正题. 基于struts2.5.10.1建立一个HelloWorld,基于注解的哈! 工具:e ...
- Alamofire源码解读系列(十二)之请求(Request)
本篇是Alamofire中的请求抽象层的讲解 前言 在Alamofire中,围绕着Request,设计了很多额外的特性,这也恰恰表明,Request是所有请求的基础部分和发起点.这无疑给我们一个Req ...
- 最近一些朋友问我,临近快毕业了专业不对口,想转行看到IT行业就业前景不错,但是编程语言众多不了解,不知道哪门语言能够快速入门掌握,短期能让我找到工作
我做互联网前端后台开发也有四年多了,一路走过来,累并快乐着.快乐比艰辛更多,源自我的兴趣驱动.初中的一个偶然的机会我接触到了计算机,从那个时候就喜欢上开始经常到网吧上网.那个时候我对计算机领域的认识是 ...
- Java数组的排序算法
在Java中,实现数组的排序算法有很多,如冒泡排序法.选择排序法.直接插入法和快速排序法等.下面介绍几种排序算法的具体 实现. 本文引用文献:Java必须知道的300个问题. 1.冒泡排序法 1.1 ...
- JSP servlet的配置与使用
1. servlet 的配置文件内容如下所示 <servlet> <description>This is the description of my J2EE com ...
- 在Excel上写程序(ExcelEx)
首先要说明的是:Ctrl+D,是执行框选的的扩展函数+号,一个单元格里多个函数用+号分隔*号,相当于链式操作(没法子,公式里不能写"."号) 虽还有很大的局限性,至少很多小程序和数 ...