[英]How to update without using flush:true
我必須更新250.000行表包含街道。 只要我用
street.save(flush:true)
它可以工作,但速度非常慢( 2 hours for 250.000
)。 如果我忽略flush:true
子句,它似乎可以快速運行,但是根本不更新。
是否需要進行總體提交,保存250.000次保存后刷新並執行該操作?
彼得
看到這個 。 它會一直為您提供幫助。 以下是與您最相關的代碼。
List batch =[]
(0..250000).each{
YourDomain domain= new YourDomain(....)
batch.add(domain)
if(batch.size()>1000){
YourDomain.withTransaction{
for(YourDomain domain in batch){
domain.save()
}
}
batch.clear()
}
session = sessionFactory.getCurrentSession()
session.clear()
}
另一個更短的解決方案:您可以不刷新記錄,但可以每次刷新500條記錄。 由於休眠涉及的步驟,刷新每個記錄基本上需要時間。 我們可以通過減少對數據庫的調用次數來減少這些。
your_record_list.eachWithIndex{ street, i ->
street.doSomeCalc()
street.save flush:0 == i % 500
}
使用domainInstance.save(flush: true)
強制SQL查詢在該時刻執行。 這並不意味着此時已將更改提交給數據庫,但是它確實會執行一些SQL。
我認為值得嘗試的第一次嘗試(因為它是最簡單的)是確保調用save()
的方法是@Transactional
。 這使Hibernate可以使用其最佳判斷(盡可能長地延遲SQL),而不必強制刷新Hibernate會話。
import org.springframework.transaction.annotation.Transactional
class SomeController {
@Transactional
def save() {
def streets = /* Some GORM query */
streets.each {
/* Make updates here */
it.save() /* No flush needed because the method is transactional */
}
}
}
只有在以下情況下,才有另一個選項可用:
第二個標准很微妙,可以使您發瘋。 DetachedCriteria.updateAll(Map)
看不到未提交的更改。 例如,如果您手動進行更改...
someInstance.foo = 'bar'
someInstance.save(flush: true)
...然后使用updateAll()
對同一個實例進行操作, updateAll()
不會知道您之前所做的事情。
因此,如果情況允許,您可以使用updateAll()
:
@Transactional
def save() {
def streets = Street.where { /* a GORM where query */}
streets.updateAll([propertyA: valueA, propertyB: valueB])
}
如您所知, updateAll()
根據property-name / property-value Map
修改每個合格的域類實例。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.