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="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 size
5         //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 (?, ?, ?, ?)
......

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM