標籤:des c style class blog code
批量處理資料是指在一個事務中處理大量資料.
在應用程式層進行大量操作, 主要有以下方式:
- 通過 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 方法返回
通過 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的事件處理系統忽略掉。
public class HibernateTest {private SessionFactory sessionFactory;private Session session;private Transaction transaction;@Beforepublic void init(){Configuration configuration = new Configuration().configure();ServiceRegistry serviceRegistry = new ServiceRegistryBuilder().applySettings(configuration.getProperties()) .buildServiceRegistry();sessionFactory = configuration.buildSessionFactory(serviceRegistry);session = sessionFactory.openSession();transaction = session.beginTransaction();}@Afterpublic void destroy(){transaction.commit();session.close();sessionFactory.close();}@Testpublic void testBatch(){session.doWork(new Work() {@Overridepublic void execute(Connection connection) throws SQLException {//通過 JDBC 原生的 API 進行操作, 效率最高, 速度最快!}});}}