首页 > 代码库 > JPA中以HibernatePersistence为provider的批量插入问题

JPA中以HibernatePersistence为provider的批量插入问题

为什么要批量插入

要插入10000条数据,如果不批量插入的话,那么我们执行的sql语句将是10000条insert

insert into member (group_id, user_id, role, extend) values (101, 100, 3, NULL)
insert into member (group_id, user_id, role, extend) values (101, 101, 3, NULL)
insert into member (group_id, user_id, role, extend) values (101, 102, 3, NULL)
insert into member (group_id, user_id, role, extend) values (101, 103, 3, NULL)

......

如果是批量插入,一批次插入50条,那么10000条数据将生成200条insert语句

insert into member (group_id, user_id, role, extend) VALUES (101, 100, 3, NULL), (101, 101, 3, NULL), ..., (101, 149, 3, NULL)

insert into member (group_id, user_id, role, extend) VALUES (101, 100, 3, NULL), (101, 101, 3, NULL), ..., (101, 149, 3, NULL)

好了,以上是jdbc级别的批量插入,换言之,我们需要JPA提供批量插入功能

 

JPA批量插入

搜索了Stackoverflow,似乎JPA本身并没有对批量插入的支持

http://stackoverflow.com/questions/7440397/how-to-do-the-batch-insert-in-jpa

 

Hibernate批量插入

因为使用Hibernate作为JPA的provider实现,因此我们可以使用Hibernate提供的批量插入功能

查阅hibernate文档

http://docs.jboss.org/hibernate/core/3.3/reference/en/html/batch.html

(1) 首先要在hibernate配置文件中配置属性

<property name="hibernate.jdbc.batch_size" value="http://www.mamicode.com/20" /> <!-- value文档建议在10-50间 -->

(2) 批量插入代码示例

1 for ( int i=0; i<100000; i++ ) {2     Customer customer = new Customer(.....);3     session.save(customer);4     if ( i % 20 == 0 ) { //20, same as the JDBC batch size5         //flush a batch of inserts and release memory:6         session.flush();7         session.clear();8     }9 }

 

注意

如果批量插入的实体主键为@GeneratedValue(strategy=IDENTITY)类型,则hibernate会透明关闭在jdbc级别的批量插入;因为实际上,每次插入该实体的一个实例,hibernate都需要搜索该实例的主键;想想在代码中,我们persist实例之后,就能够通过get方法获取实例的主键;

实验结果也说明了这点

实体定义

 1 @Entity 2 @Table (name="member") 3 public class GroupUser { 4   @Id 5   @GeneratedValue(strategy=IDENTITY) 6   @Column(name="id", nullable=true, unique=true) 7   private Integer id; 8  9   ......10 11 }

 

实验代码

 1 Session session = (Session)em.getDelegate(); 2 session.setFlushMode(FlushMode.MANUAL); 3  4 for (int i = 0; i < userIds.size(); ++i) { 5   session.save(new GroupUser(groupId, userIds.get(i), role)); 6   if (i % 20 == 0) { 7     session.flush(); 8     session.clear(); 9   }10 }

 

日志输出

Hibernate: insert into member (group_id, user_id, role, extend) values (?, ?, ?, ?)
Hibernate: insert into member (group_id, user_id, role, extend) values (?, ?, ?, ?)
Hibernate: insert into member (group_id, user_id, role, extend) values (?, ?, ?, ?)
Hibernate: insert into member (group_id, user_id, role, extend) values (?, ?, ?, ?)
......

 

JPA中以HibernatePersistence为provider的批量插入问题