hibernate 批量增加 修改 刪除

2021-09-08 17:40:20 字數 3473 閱讀 1295

hibernate完全以物件導向的方式來運算元據庫,當程式裡以物件導向的方式操作持久化物件時,將被自動轉換為對資料庫的操作。例如呼叫session的delete()方法來刪除持久化物件,hibernate將負責刪除對應的資料記錄;當執行持久化物件的set方法時,hibernate將自動轉換為對應的update方法,修改資料庫的對應記錄。

問題是如果需要同時更新100 000條記錄,是不是要逐一載入100 000條記錄,然後依次呼叫set方法——這樣不僅繁瑣,資料訪問的效能也十分糟 糕。對這種批量處理的場景,hibernate提供了批量處理的解決方案,下面分別從批量插入、批量更新和批量刪除3個方面介紹如何面對這種批量處理的情 形。

如果需要將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級別的快取外,最好關閉sessionfactory級別的二級快取。否則,即使手動清空session級別的快取,但因為在sessionfactory級別還有快取,也可能引發異常。

上面介紹的方法同樣適用於批量更新資料,如果需要返回多行資料,可以使用scroll()方法,從而可充分利用伺服器端游標所帶來的效能優勢。下面是進行批量更新的**片段:

private

void testuser()throws

exception

}tx.commit();

hibernateutil.closesession();

}

當然,同樣可以使用hibernate配置來實現同樣功能:

在hibernate.cfg.xml中插入:

50

//每50條語句提交一次

false

//關閉二級快取

通過這種方式,雖然可以執行批量更新,但效果非常不好。執行效率不高,而且需要先執行資料查詢,然後再執行資料更新,並且這種更新將是逐行更新,即每更新一行記錄,都需要執行一條update語句,效能非常低下。

為了避免這種情況,hibernate提供了一種類似於sql的批量更新和批量刪除的hql語法。

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語句影響的記錄行 數。

4.2.4也可以用preparedstatemen進行批量插入,

如下示例:

session session =hibernateutil.getsessionfactory().getcurrentsession(); 

transaction tran =session.begintransaction();

session.setcachemode(cachemode.ignore);

preparedstatement stmt;

try

stmt.executebatch();

} catch

(sqlexception e)

tran.commit();

session.close();

hibernateutil.getsessionfactory().close();

hibernate批量修改,批量刪除

在hibernate應用中如何處理批量更新和批量刪除?批量更新是指在乙個事務中更新大批量資料,批量刪除是指在乙個事務中刪除大批量資料。以下程式直接通過hibernate api批量更新customers表中年齡大於零的所有記錄的age欄位 tx session.begintransaction it...

hibernate批量修改,批量刪除

在hibernate應用中如何處理批量更新和批量刪除?批量更新是指在乙個事務中更新大批量資料,批量刪除是指在乙個事務中刪除大批量資料。以下程式直接通過hibernate api批量更新customers表中年齡大於零的所有記錄的age欄位 tx session.begintransaction it...

hibernate批量刪除

一般而言,hibernate的批量刪除的寫法有兩種,一種是hibernate內建的批量刪除,不過他的批量刪除是將每條記錄逐一生成刪除 語句,其效率極低,當然我們可以使用抓取策略給其進行優化,不過這只是亡羊補牢的方法,效率的提公升依然不能讓我們滿意,很不推薦使用 另一種是由 拼串 形成的hql語句,其...