我的Grails項目從升級到1.3.7和2.4.0修復與新的Grails版本的各種問題後,後洗淨模式中,我意識到,沒有做過任何對象的變化將是除了調用save(flush:true)
外,其他所有(除此之外)都一直存在。Grails的改變從自動到手動
對於Grails 1.3.7,使用save()
保存域實例時的默認行爲是,由於休眠flushMode =>FlushMode.AUTO
,更改會自動保留。在Grails 2.4.0中,這不再是事實。任何控制器操作或服務類中的hibernate會話的默認flushMode爲FlushMode.MANUAL
。自舉,它有一個FlushMode.AUTO
值和一個控制器動作,其中它具有價值FlushMode.MANUAL
檢索sessionFactory.currentSession.flushMode
時
事情變得陌生了。這可以通過創建一個新的Grails應用程序,並把println "flushMode = $sessionFactory.currentSession.flushMode"
自舉和一個控制器動作進行驗證(例如指數())。
我已經通過各類論壇搜索的最後2天,並沒有發現任何合理的解釋,爲什麼這個曾在Grails的2.4.0改變(或者甚至在較早版本)。我只找到評論說,它的種類有風險有FlushMode.MANUAL
,因爲你可以查詢數據庫時,一些人已被修改後碰到過時對象。
我知道:
- 與
grails.gorm.autoFlush = true
在配置你可以強制刷新:真正到每一個省() - 在Hibernate3和hibernate4默認flushMode是
FlushMode.AUTO
- 其無法設置flushMode在Config.groovy和DataSource.groovy中。我嘗試了所有這一切,並沒有做任何工作:
hibernate.flush.mode = 'auto' hibernate.flushMode = 'auto' hibernate.session.flush.mode = 'auto' hibernate.session.flushMode = 'auto' dataSource.hibernate.flush.mode = 'auto' dataSource.hibernate.flushMode = 'auto' dataSource.hibernate.session.flush.mode = 'auto' dataSource.hibernate.session.flushMode = 'auto' dataSource.flush.mode = 'auto' dataSource.flushMode = 'auto' dataSource.session.flush.mode = 'auto' dataSource.session.flushMode = 'auto'
請有人可以扔在這個小光?
其實我想知道的話,Grails的2.4.0 FlushMode.MANUAL
現在所需的默認?
如果是這樣:
- 什麼是評論「...的建議是不是我們完全禁用自動清空模式......」由彼得·萊德布魯克在GRAILS-7180
- 什麼是最佳實踐不會遇到過時對象的問題,特別是在對域對象執行復雜操作時,修改,創建新實例和查詢都是混合的。
非常感謝 - 安迪
在閱讀Graemes回答,他的意見,我想更好地澄清什麼,我掙扎,並添加了證明行爲以下簡化域和控制器類:
域類信息:
class Msg {
String text
static constraints = {
text nullable:true
}
}
和味精控制器:
class MsgController {
def sessionFactory
def index = {
def out = ["*** flushMode when in controller/index = \
$sessionFactory.currentSession.flushMode"]
Msg.list().each { out << "$it.id: text=$it.text" }
render out.join('<br>')
}
// this save does persist the new msg object,
// even if flushMode = MANUAL
def save1 = {
def out = ["*** flushMode when in controller/save = \
$sessionFactory.currentSession.flushMode"]
def msg = new Msg(text:'hallo')
if (!msg.save()) {
out << "msg has errors! " + msg.errors
}
out << "msg $msg.id created with text = $msg.text"
render out.join('<br>')
}
// this save does NOT persist the new msg object, even if its valid
// (difference is calling hasErrors()
def save2 = {
def out = ["*** flushMode when in controller/save = \
$sessionFactory.currentSession.flushMode"]
def msg = new Msg(text:'hallo')
if (msg.hasErrors() && !msg.save()) {
out << "msg has errors! " + msg.errors
}
out << "msg $msg.id created with text = $msg.text"
render out.join('<br>')
}
}
所以調用http://localhost/appname/msg/save1
輸出爲:
*** flushMode when in controller/save1 = MANUAL
msg 1 created with text = hallo
在這裏,我不明白,爲什麼Hibernate持久化對象,即使你flushMode是MANUAL。
,並呼籲http://localhost/appname/msg/save2
當輸出爲:
*** flushMode when in controller/save2 = MANUAL
msg null created with text = hallo
對象沒有得到持續,因爲Hibernate沒有發出沖水,從而從未調用SQL「更新...」命令。
但現在看來,不僅flushMode是一個問題,而且如果有人調用hasErrors()或不!我更加困惑......
如果你在Grails 1.3.7中做這個例子,保存動作(save1和save2)會保持新創建的msg對象!
感謝您的解釋。那是有道理的。但是爲什麼Grails在控制器動作中切換到MANUAL,即使沒有域對象被保存(完全使用)?我用一個控制器編寫了一個小小的Grails應用程序,沒有任何領域類來驗證。在控制器索引操作中,我只放置了1 LOC'println「flushMode = $ sessionFactory.currentSession.flushMode」 –
對於讀取操作,Grails使用只讀事務。只讀事務使用手動刷新模式。讀操作使用只讀事務的原因是因爲它提高了性能,因爲Hibernate不需要對只讀對象進行髒檢查。這可能是你所看到的。 –
查看原始問題的更新域和控制器示例 –