欧美三区_成人在线免费观看视频_欧美极品少妇xxxxⅹ免费视频_a级毛片免费播放_鲁一鲁中文字幕久久_亚洲一级特黄

Hibernate批量處理(Batch processing)

系統 1612 0
使用Hibernate將 100 000 條記錄插入到數據庫的一個很自然的做法可能是這樣的

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
for ( int i=0; i<100000; i++ ) {
??? Customer customer = new Customer(.....);
??? session.save(customer);
}
tx.commit();
session.close();
這段程序大概運行到 50 000 條記錄左右會失敗并拋出 內存溢出異常(OutOfMemoryException) 。 這是因為 Hibernate 把所有新插入的 客戶(Customer)實例在 session級別的緩存區進行了緩存的緣故。

我們會在本章告訴你如何避免此類問題。首先,如果你要執行批量處理并且想要達到一個理想的性能, 那么使用JDBC的批量(batching)功能是至關重要。將JDBC的批量抓取數量(batch size)參數設置到一個合適值 (比如,10-50之間):

hibernate.jdbc.batch_size 20
注意,假若你使用了identiy標識符生成器,Hibernate在JDBC級別透明的關閉插入語句的批量執行。

你也可能想在執行批量處理時關閉二級緩存:

hibernate.cache.use_second_level_cache false
但是,這不是絕對必須的,因為我們可以顯式設置CacheMode來關閉與二級緩存的交互。

13.1. 批量插入(Batch inserts)
如果要將很多對象持久化,你必須通過經常的調用 flush() 以及稍后調用 clear() 來控制第一級緩存的大小。

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
??
for ( int i=0; i<100000; i++ ) {
??? Customer customer = new Customer(.....);
??? session.save(customer);
??? if ( i % 20 == 0 ) { //20, same as the JDBC batch size //20,與JDBC批量設置相同
??????? //flush a batch of inserts and release memory:
??????? //將本批插入的對象立即寫入數據庫并釋放內存
??????? session.flush();
??????? session.clear();
??? }
}
??
tx.commit();
session.close();
13.2. 批量更新(Batch updates)
此方法同樣適用于檢索和更新數據。此外,在進行會返回很多行數據的查詢時, 你需要使用 scroll() 方法以便充分利用服務器端游標所帶來的好處。

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
??
ScrollableResults customers = session.getNamedQuery("GetCustomers")
??? .setCacheMode(CacheMode.IGNORE)
??? .scroll(ScrollMode.FORWARD_ONLY);
int count=0;
while ( customers.next() ) {
??? Customer customer = (Customer) customers.get(0);
??? customer.updateStuff(...);
??? if ( ++count % 20 == 0 ) {
??????? //flush a batch of updates and release memory:
??????? session.flush();
??????? session.clear();
??? }
}
??
tx.commit();
session.close();
13.3. StatelessSession (無狀態session)接口
作為選擇,Hibernate提供了基于命令的API,可以用detached object的形式把數據以流的方法加入到數據庫,或從數據庫輸出。StatelessSession沒有持久化上下文,也不提供多少高層的生命周期語義。特別是,無狀態session不實現第一級cache,也不和第二級緩存,或者查詢緩存交互。它不實現事務化寫,也不實現臟數據檢查。用stateless session進行的操作甚至不級聯到關聯實例。stateless session忽略集合類(Collections)。通過stateless session進行的操作不觸發Hibernate的事件模型和攔截器。無狀態session對數據的混淆現象免疫,因為它沒有第一級緩存。無狀態session是低層的抽象,和低層JDBC相當接近。

StatelessSession session = sessionFactory.openStatelessSession();
Transaction tx = session.beginTransaction();
??
ScrollableResults customers = session.getNamedQuery("GetCustomers")
??? .scroll(ScrollMode.FORWARD_ONLY);
while ( customers.next() ) {
??? Customer customer = (Customer) customers.get(0);
??? customer.updateStuff(...);
??? session.update(customer);
}
??
tx.commit();
session.close();
注意在上面的例子中,查詢返回的Customer實例立即被脫管(detach)。它們與任何持久化上下文都沒有關系。

StatelessSession 接口定義的insert(), update() 和 delete()操作是直接的數據庫行級別操作,其結果是立刻執行一條INSERT, UPDATE 或 DELETE 語句。因此,它們的語義和Session 接口定義的save(), saveOrUpdate() 和delete() 操作有很大的不同。
13.4. DML(數據操作語言)風格的操作(DML-style operations)
hence manipulating (using the SQL Data Manipulation Language (DML) statements: INSERT, UPDATE, DELETE) data directly in the database will not affect in-memory state. However, Hibernate provides methods for bulk SQL-style DML statement execution which are performed through the Hibernate Query Language (第 14 章 HQL: Hibernate查詢語言). 就像已經討論的那樣,自動和透明的 對象/關系 映射(object/relational mapping)關注于管理對象的狀態。 這就意味著對象的狀態存在于內存,因此直接操作 (使用 SQL Data Manipulation Language(DML,數據操作語言)語句 :INSERT ,UPDATE 和 DELETE) 數據庫中的數據將不會影響內存中的對象狀態和對象數據。 不過,Hibernate提供通過Hibernate查詢語言(第 14 章 HQL: Hibernate查詢語言)來執行大批 量SQL風格的DML語句的方法。

UPDATE 和 DELETE語句的語法為: ( UPDATE | DELETE ) FROM? EntityName (WHERE where_conditions)? 有幾點說明:

在FROM子句(from-clause)中,FROM關鍵字是可選的

在FROM子句(from-clause)中只能有一個實體名,它可以是別名。如果實體名是別名,那么任何被引用的屬性都必須加上此別名的前綴;如果不是別名,那么任何有前綴的屬性引用都是非法的。

不能在大批量HQL語句中使用第 14.4 節 “join 語法的形式”(顯式或者隱式的都不行)。不過在WHERE子句中可以使用子查詢??梢栽趙here子句中使用子查詢,子查詢本身可以包含join。

整個WHERE子句是可選的。

舉個例子,使用Query.executeUpdate()方法執行一個HQL UPDATE語句(: (方法命名是來源于JDBC's PreparedStatement.executeUpdate()):

Session session = sessionFactory.openSession();
? Transaction tx = session.beginTransaction();

? String hqlUpdate = "update Customer c set c.name = :newName where c.name = ldName";
? // or String hqlUpdate = "update Customer set name = :newName where name = ldName";
? int updatedEntities = s.createQuery( hqlUpdate )
????????? .setString( "newName", newName )
????????? .setString( "oldName", oldName )
????????? .executeUpdate();
? tx.commit();
? session.close();
HQL UPDATE語句,默認不會影響更新實體的第 5.1.7 節 “版本(version)(可選)”或者第 5.1.8 節 “timestamp (可選)”屬性值。這和EJB3規范是一致的。但是,通過使用versioned update,你可以強制Hibernate正確的重置version或者timestamp屬性值。這通過在UPDATE關鍵字后面增加VERSIONED關鍵字來實現的。

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
String hqlVersionedUpdate = "update versioned Customer set name = :newName where name = ldName";
int updatedEntities = s.createQuery( hqlUpdate )
??????? .setString( "newName", newName )
??????? .setString( "oldName", oldName )
??????? .executeUpdate();
tx.commit();
session.close();
注意,自定義的版本類型(org.hibernate.usertype.UserVersionType)不允許和update versioned語句聯用。

執行一個HQL DELETE,同樣使用 Query.executeUpdate() 方法:

Session session = sessionFactory.openSession();
? Transaction tx = session.beginTransaction();

? String hqlDelete = "delete Customer c where c.name = ldName";
? // or String hqlDelete = "delete Customer where name = ldName";
? int deletedEntities = s.createQuery( hqlDelete )
????????? .setString( "oldName", oldName )
????????? .executeUpdate();
? tx.commit();
? session.close();
由Query.executeUpdate()方法返回的整型值表明了受此操作影響的記錄數量。 注意這個數值可能與數據庫中被(最后一條SQL語句)影響了的“行”數有關,也可能沒有。一個大批量HQL操作可能導致多條實際的SQL語句被執行, 舉個例子,對joined-subclass映射方式的類進行的此類操作。這個返回值代表了實際被語句影響了的記錄數量。在那個joined-subclass的例子中, 對一個子類的刪除實際上可能不僅僅會刪除子類映射到的表而且會影響“根”表,還有可能影響與之有繼承關系的joined-subclass映射方式的子類的表。

INSERT語句的偽碼是: INSERT INTO EntityName properties_list select_statement. 要注意的是:

只支持INSERT INTO ... SELECT ...形式,不支持INSERT INTO ... VALUES ...形式.

properties_list和SQL INSERT語句中的字段定義(column speficiation)類似。對參與繼承樹映射的實體而言,只有直接定義在給定的類級別的屬性才能直接在properties_list中使用。超類的屬性不被支持;子類的屬性無意義。換句話說,INSERT天生不支持多態。

select_statement可以是任何合法的HQL選擇查詢,不過要保證返回類型必須和要插入的類型完全匹配。目前,這一檢查是在查詢編譯的時候進行的,而不是把它交給數據庫。注意,在HibernateType間如果只是等價(equivalent)而非相等(equal),會導致問題。定義為org.hibernate.type.DateType和org.hibernate.type.TimestampType的兩個屬性可能會產生類型不匹配錯誤,雖然數據庫級可能不加區分或者可以處理這種轉換。

對id屬性來說,insert語句給你兩個選擇。你可以明確地在properties_list表中指定id屬性(這樣它的值是從對應的select表達式中獲得),或者在properties_list中省略它(此時使用生成指)。后一種選擇只有當使用在數據庫中生成值的id產生器時才能使用;如果是“內存”中計算的類型生成器,在解析時會拋出一個異常。注意,為了說明這一問題,數據庫產生值的生成器是org.hibernate.id.SequenceGenerator(和它的子類),以及任何org.hibernate.id.PostInsertIdentifierGenerator接口的實現。這兒最值得注意的意外是org.hibernate.id.TableHiLoGenerator,它不能在此使用,因為它沒有得到其值的途徑。

對映射為version 或 timestamp的屬性來說,insert語句也給你兩個選擇,你可以在properties_list表中指定(此時其值從對應的select表達式中獲得),或者在properties_list中省略它(此時,使用在org.hibernate.type.VersionType 中定義的seed value(種子值))。

執行HQL INSERT語句的例子如下:

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

String hqlInsert = "insert into DelinquentAccount (id, name) select c.id, c.name from Customer c where ...";
int createdEntities = s.createQuery( hqlInsert )
??????? .executeUpdate();
tx.commit();
session.close();

Hibernate批量處理(Batch processing)


更多文章、技術交流、商務合作、聯系博主

微信掃碼或搜索:z360901061

微信掃一掃加我為好友

QQ號聯系: 360901061

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描下面二維碼支持博主2元、5元、10元、20元等您想捐的金額吧,狠狠點擊下面給點支持吧,站長非常感激您!手機微信長按不能支付解決辦法:請將微信支付二維碼保存到相冊,切換到微信,然后點擊微信右上角掃一掃功能,選擇支付二維碼完成支付。

【本文對您有幫助就好】

您的支持是博主寫作最大的動力,如果您喜歡我的文章,感覺我的文章對您有幫助,請用微信掃描上面二維碼支持博主2元、5元、10元、自定義金額等您想捐的金額吧,站長會非常 感謝您的哦?。。?/p>

發表我的評論
最新評論 總共0條評論
主站蜘蛛池模板: 国产伦精品一区二区三区高清 | 久久精彩视频 | 2019天天操夜夜操 | 草樱av | 精品国精品国产自在久国产应用 | 视频一区二区三区免费观看 | 另类二区三四 | 欧美一区二区三区视频 | 日本高清视频免费在线观看 | 精品一区二区久久久久久久网站 | 久久久.com| 国产精品xxxav免费视频 | 亚洲黄色免费观看 | 李宗瑞国产福利视频一区 | 国产精品第三页在线看 | 久草视频在线观 | 亚洲黄色免费观看 | 久久亚洲国产成人影院 | 色综合网址| 天天天天天操 | 亚洲精品久久久一区二区三区 | 麻豆久久久久 | 国产一区精品 | 欧美日本一区视频免费 | 国产亚洲欧美在线人成aaaa | 一级鲁丝片 | 四虎884a | 国产一区在线免费观看 | 日本一区二区久久久 | 日韩伦理免费在线观看 | 亚洲欧美偷拍自拍 | 精品久久一区二区 | 四虎欧美在线观看免费 | 久在线播放 | 99国产在线视频有精品视频 | 99午夜高清在线视频在观看 | 色94色 成人 | 国产精品秒播无毒不卡 | 国产伦精品一区二区 | 精品一区二区三区免费毛片 | 日韩精品视频免费在线观看 |