hibernate批量操作實例詳解。本站提示廣大學習愛好者:(hibernate批量操作實例詳解)文章只能為提供參考,不一定能成為您想要的結果。以下是hibernate批量操作實例詳解正文
本文實例講述了hibernate批量操作的辦法。分享給年夜家供年夜家參考,詳細以下:
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++ ) { User u = new User (.....); session.save(customer); } tx.commit(); session.close();
但跟著這個法式的運轉,總會在某個時刻運轉掉敗,而且拋出OutOfMemoryException(內存溢出異常)。這是由於Hibernate的Session持有一個必選的一級緩存,一切的User實例都將在Session級其余緩存區停止了緩存的原因。
為懂得決這個成績,有個異常簡略的思緒:准時將Session緩存的數據刷新入數據庫,而不是一向在Session級別緩存。可以斟酌設計一個累加器,每保留一個User實例,累加器增長1。依據累加器的值決議能否須要將Session緩存中的數據刷入數據庫。
上面是增長100 000個User實例的代碼片斷:
private void testUser()throws Exception { //翻開Session Session session = HibernateUtil.currentSession(); //開端事務 Transaction tx = session.beginTransaction(); //輪回100 000次,拔出100 000筆記錄 for (int i = 0 ; i < 1000000 ; i++ ) { //創立User實例 User u1 = new User(); u1.setName("xxxxx" + i); u1.setAge(i); u1.setNationality("china"); //在Session級別緩存User實例 session.save(u1); //每當累加器是20的倍數時,將Session中的數據刷入數據庫,並清空Session緩存 if (i % 20 == 0) { session.flush(); session.clear(); tx.commit(); tx = session.beginTransaction(); } } //提交事務 tx.commit(); //封閉事務 HibernateUtil.closeSession(); }
下面代碼中,當i%20 == 0時,手動將Session處的緩存數據寫入數據庫,並手動提交事務。假如不提交事務,數據將仍然緩存在事務處——未進入數據庫,也將惹起內存溢出的異常。
這是對Session級別緩存的處置,還應當經由過程以下設置裝備擺設來封閉SessionFactory的二級緩存。
hibernate.cache.use_second_level_cache false
留意:除要手動清空Session級其余緩存外,最好封閉SessionFactory級其余二級緩存。不然,即便手動清空Session級其余緩存,但由於在SessionFactory級別還有緩存,也能夠激發異常。
2 批量更新
下面引見的辦法異樣實用於批量更新數據,假如須要前往多行數據,可使用scroll()辦法,從而可充足應用辦事器端游標所帶來的機能優勢。上面是停止批量更新的代碼片斷:
private void testUser()throws Exception { //翻開Session Session session = HibernateUtil.currentSession(); //開端事務 Transaction tx = session.beginTransaction(); //查詢出User表中的一切記載 ScrollableResults users = session.createQuery("from User") .setCacheMode(CacheMode.IGNORE) .scroll(ScrollMode.FORWARD_ONLY); int count=0; //遍歷User表中的全體記載 while ( users.next() ) { User u = (User) users.get(0); u.setName("新用戶名" + count); //當count為20的倍數時,將更新的成果從Session中flush到數據庫 if ( ++count % 20 == 0 ) { session.flush(); session.clear(); } } 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 { //翻開Session Session session = HibernateUtil.currentSession(); //開端事務 Transaction tx = session.beginTransaction(); //界說批量更新的HQL語句 String hqlUpdate = "update User set name = :newName"; //履行更新 int updatedEntities = session.createQuery( hqlUpdate ) .setString( "newName", "新名字" ) .executeUpdate(); //提交事務 tx.commit(); HibernateUtil.closeSession(); }
從下面代碼中可以看出,這類語法異常相似於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 { //翻開Session實例 Session session = HibernateUtil.currentSession(); //開端事務 Transaction tx = session.beginTransaction(); //界說批量刪除的HQL語句 String hqlUpdate = "delete User"; //履行批量刪除 int updatedEntities = session.createQuery( hqlUpdate ) .executeUpdate(); //提交事務 tx.commit(); //封閉Session HibernateUtil.closeSession(); }
由Query.executeUpdate()辦法前往一個整型值,該值是受此操作影響的記載數目。現實上,Hibernate的底層操作是經由過程JDBC完成的。是以,假如有批量的UPDATE或DELETE操作被轉換成多條UPDATE或DELETE語句,該辦法前往的是最初一條SQL語句影響的記載行數。
願望本文所述對年夜家基於Hibernate框架的Java法式設計有所贊助。