一
批量修改和刪除
在Hibernate
中
如果需要對任何數據進行修改和刪除操作
都需要先執行查詢操作
在得到要修改或者刪除的數據後
再對該數據進行相應的操作處理
在數據量少的情況下采用這種處理方式沒有問題
但需要處理大量數據的時候就可能存在以下的問題
占用大量的內存
需要多次執行update/delete語句
而每次執行只能處理一條數據
以上兩個問題的出現會嚴重影響系統的性能
因此
在Hibernate
中引入了用於批量更新或者刪除數據的HQL語句
這樣
開發人員就可以一次更新或者刪除多條記錄
而不用每次都一個一個地修改或者刪除記錄了
如果要刪除所有的User對象(也就是User對象所對應表中的記錄)
則可以直接使用下面的HQL語句
delete User
而在執行這個HQL語句時
需要調用Query對象的executeUpdate()方法
具體的實例如下所示
String HQL=
delete User
;
Query query=session
createQuery(HQL)
int size=query
executeUpdate()
采用這種方式進行數據的修改和刪除時與直接使用JDBC的方式在性能上相差無幾
是推薦使用的正確方法
如果不能采用HQL語句進行大量數據的修改
也就是說只能使用取出再修改的方式時
也會遇到批量插入時的內存溢出問題
所以也要采用上面所提供的處理方法來進行類似的處理
二
使用SQL執行批量操作
在進行批量插入
修改和刪除操作時
直接使用JDBC來執行原生態的SQL語句無疑會獲得最佳的性能
這是因為在處理的過程中省略或者簡化了以下處理內容
● HQL語句到SQL語句的轉換
● Java對象的初始化
● Java對象的緩存處理
但是在直接使用JDBC執行SQL語句時
有一個最重要的問題就是要處理緩存中的Java對象
因為通過這種底層方式對數據的修改將不能通知緩存去進行相應的更新操作
以保證緩存中的對象與數據庫中的數據是一致的
三
提升數據庫查詢的性能
數據庫查詢性能的提升也是涉及到開發中的各個階段
在開發中選用正確的查詢方法無疑是最基礎也最簡單的
SQL語句的優化
使用正確的SQL語句可以在很大程度上提高系統的查詢性能
獲得同樣數據而采用不同方式的SQL語句在性能上的差距可能是十分巨大的
由於Hibernate是對JDBC的封裝
SQL語句的產生都是動態由Hibernate自動完成的
Hibernate產生SQL語句的方式有兩種
一種是通過開發人員編寫的HQL語句來生成
另一種是依據開發人員對關聯對象的訪問來自動生成相應的SQL語句
至於使用什麼樣的SQL語句可以獲得更好的性能要依據數據庫的結構以及所要獲取數據的具體情況來進行處理
在確定了所要執行的SQL語句後
可以通過以下三個方面來影響Hibernate所生成的SQL語句
HQL語句的書寫方法
查詢時所使用的查詢方法
對象關聯時所使用的抓取策略
使用正確的查詢方法
在前面已經介紹過
執行數據查詢功能的基本方法有兩種
一種是得到單個持久化對象的get()方法和load()方法
另一種是Query對象的list()方法和iterator()方法
在開發中應該依據不同的情況選用正確的方法
get()方法和load()方法的區別在於對二級緩存的使用上
load()方法會使用二級緩存
而get()方法在一級緩存沒有找到的情況下會直接查詢數據庫
不會去二級緩存中查找
在使用中
對使用了二級緩存的對象進行查詢時最好使用load()方法
以充分利用二級緩存來提高檢索的效率
list()方法和iterator()方法之間的區別可以從以下幾個方面來進行比較
執行的查詢不同
list()方法在執行時
是直接運行查詢結果所需要的查詢語句
而iterator()方法則是先執行得到對象ID的查詢
然後再根據每個ID值去取得所要查詢的對象
因此
對於list()方式的查詢通常只會執行一個SQL語句
而對於iterator()方法的查詢則可能需要執行N+
條SQL語句(N為結果集中的記錄數)
iterator()方法只是可能執行N+
條數據
具體執行SQL語句的數量取決於緩存的情況以及對結果集的訪問情況
緩存的使用
list()方法只能使用二級緩存中的查詢緩存
而無法使用二級緩存對單個對象的緩存(但是會把查詢出的對象放入二級緩存中)
所以
除非重復執行相同的查詢操作
否則無法利用緩存的機制來提高查詢的效率
iterator()方法則可以充分利用二級緩存
在根據ID檢索對象的時候會首先到緩存中查找
只有在找不到的情況下才會執行相應的查詢語句
所以
緩存中對象的存在與否會影響到SQL語句的執行數量
對於結果集的處理方法不同
list()方法會一次獲得所有的結果集對象
而且它會依據查詢的結果初始化所有的結果集對象
這在結果集非常大的時候必然會占據非常多的內存
甚至會造成內存溢出情況的發生
iterator()方法在執行時不會一次初始化所有的對象
而是根據對結果集的訪問情況來初始化對象
因此在訪問中可以控制緩存中對象的數量
以避免占用過多緩存
導致內存溢出情況的發生
使用iterator()方法的另外一個好處是
如果只需要結果集中的部分記錄
那麼沒有被用到的結果對象根本不會被初始化
所以
對結果集的訪問情況也是調用iterator()方法時執行數據庫SQL語句多少的一個因素
所以
在使用Query對象執行數據查詢時應該從以上幾個方面去考慮使用何種方法來執行數據庫的查詢操作
四
使用正確的抓取策略
所謂抓取策略(fetching strategy)是指當應用程序需要利用關聯關系進行對象獲取的時候
Hibernate獲取關聯對象的策略
抓取策略可以在O/R映射的元數據中聲明
也可以在特定的HQL或條件查詢中聲明
Hibernate
定義了以下幾種抓取策略
連接抓取(Join fetching)
連接抓取是指Hibernate在獲得關聯對象時會在SELECT語句中使用外連接的方式來獲得關聯對象
查詢抓取(Select fetching)
查詢抓取是指Hibernate通過另外一條SELECT語句來抓取當前對象的關聯對象的方式
這也是通過外鍵的方式來執行數據庫的查詢
與連接抓取的區別在於
通常情況下這個SELECT語句不是立即執行的
而是在訪問到關聯對象的時候才會執行
子查詢抓取(Subselect fetching)
子查詢抓取也是指Hibernate通過另外一條SELECT語句來抓取當前對象的關聯對象的方式
與查詢抓取的區別在於它所采用的SELECT語句的方式為子查詢
而不是通過外連接
批量抓取(Batch fetching)
批量抓取是對查詢抓取的優化
它會依據主鍵或者外鍵的列表來通過單條SELECT語句實現管理對象的批量抓取
以上介紹的是Hibernate
所提供的抓取策略
也就是抓取關聯對象的手段
為了提升系統的性能
在抓取關聯對象的時機上
還有以下一些選擇
From:http://tw.wingwit.com/Article/program/Java/ky/201311/27981.html