hibernate的批量處理
hibernate完全以物件導向的方式來運算元據庫,當程式裡以物件導向的方式操作持久化物件時,將被自動轉換為對資料庫的操作。例如呼叫session的delete()方法來刪除持久化物件,hibernate將負責刪除對應的資料記錄;當執行持久化物件的set方法時,hibernate將自動轉換為對應的update方法,修改資料庫的對應記錄。
問題是如果需要同時更新100 000條記錄,是不是要逐一載入100 000條記錄,然後依次呼叫set方法——這樣不僅繁瑣,資料訪問的效能也十分糟糕。對這種批量處理的場景,hibernate提供了批量處理的解決方案,下面分別從批量插入、批量更新和批量刪除3個方面介紹如何面對這種批量處理的情形。
1 批量插入
如果需要將100 000條記錄插入資料庫,通常hibernate可能會採用如下做法:
session session = sessionfactory.opensession();
transaction tx = session.begintransaction();
for ( int i=0; i<100000; i++ )
tx.commit();
session.close();
但隨著這個程式的執行,總會在某個時候執行失敗,並且丟擲outofmemoryexception(記憶體溢位異常)。這是因為hibernate的session持有乙個必選的一級快取,所有的user例項都將在session級別的快取區進行了快取的緣故。
為了解決這個問題,有個非常簡單的思路:定時將session快取的資料重新整理入資料庫,而不是一直在session級別快取。可以考慮設計乙個累加器,每儲存乙個user例項,累加器增加1。根據累加器的值決定是否需要將session快取中的資料刷入資料庫。
下面是增加100 000個user例項的**片段:
private void testuser()throws exception
} //提交事務
tx.commit();
//關閉事務
hibernateutil.closesession();
}上面**中,當i%20 == 0時,手動將session處的快取資料寫入資料庫,並手動提交事務。如果不提交事務,資料將依然快取在事務處——未進入資料庫,也將引起記憶體溢位的異常。
這是對session級別快取的處理,還應該通過如下配置來關閉sessionfactory的二級快取。
hibernate.cache.use_second_level_cache false
注意:除了要手動清空session級rqzxus別的快取外,最好關閉sessionfactory級別的二級快取。否則,即使手動清空session級別的快取,但因為在sessionfactory級別還有快取,也可能引發異常。
2 批量更新
上面介紹的方法同樣適用於批量更新資料,如果需要返回多行資料,可以使用scroll()方法,從而可充分利用伺服器端游標所帶來的效能優勢。下面是進行批量更新的**片段:
private void testuser()throws exception
} tx.commit();
hibernateutil.closesession();
}通過這種方式,雖然可以執行批量更新,但效果非常不好。執行效率不高,而且需要先執行資料查詢,然後再執行資料更新,並且這種更新將是逐行更新,即每更新一行記錄,都需要執行一條update語句,效能非常低下。
為了避免這種情況,hibernate提供了一種類似於sql的批量更新和批量刪除的hql語法。
3 sql風格的批量更新/刪除
hibernate提供的hql語句也支援批量的update和delete語法。
批量update和delete語句的語法格式如下:
update | delete from? classname [where where_conditions]
關於上面的語法格式有以下四點值得注意:
● 在from子句中,from關鍵字是可選的。即完全可以不寫from關鍵字。
● 在from子句中只能有乙個類名,該類名不能有別名。
● 不能在批量hql語句中使用連線,顯式的或隱式的都不行。程式設計客棧但可以在where子句中使用子查詢。
● 整個where子句是可選的。
假設,需要批量更改user類例項的name屬性,可以採用如下**片段完成:
private void testuser()throws exception
從上面**中可以看出,這種語法非常類似於preparedstatement的executeupdate語法。實際上,hql的這種批量更新就是直接借鑑了sql語法的update語句。
注意:使用這種批量更新語法時,通常只需要執行一次sql的update語句,就可以完成所有滿足條件記錄的更新。但也可能需要執行多條update語句,這是因為有繼承對映等特殊情況,例如有乙個person例項,它有customer的子類例項。當批量更新person例項時,也需要更新customer例項。如果採用joined-subclass或union-subclass對映策略,person和customer例項儲存在不同的表中,因此可能需要多條update語句。
執行乙個hql delete,同樣使用 query.executeupdate() 方法,下面是一次刪除上面全部記錄的**片段:
private void testuser()throws exception
由query.executeupdate()方法返回乙個整型值,該值是受此操作影響的記錄數量。實際上,hibernate的底層操作是通過jdbc完成的。因此,如果有批量的update或delete操作被轉換成多條update或delete語句,該方法返回的是最後一條sql語句影響的記錄行數。
本文標題: hibernate批量操作例項詳解
本文位址:
Hibernate的批量操作
在實際的操作中,會經常的遇到批量的操作,使用hibernate將 100條記錄插入到資料庫的乙個很自然的做法可能是這樣的 session session sessionfactory.opensession transaction tx session.begintransaction for in...
Hibernate的批量操作
在實際的操作中,會經常的遇到批量的操作,使用hibernate將 100條記錄插入到資料庫的乙個很自然的做法可能是這樣的 session session sessionfactory.opensession transaction tx session.begintransaction for in...
Hibernate的批量操作
在實際的操作中,會經常的遇到批量的操作,使用hibernate將 100條記錄插入到資料庫的乙個很自然的做法可能是這樣的 1 session session sessionfactory.opensession 2 transaction tx session.begintransaction 3f...