Grails 2.5.5事務問題。grails 2.5:failOnError:false在錯誤時總是失敗。如何不失敗的錯誤?
我們有一個get Balance調用API調用,它是一個調用少量服務的簡單控制器。它做2件事,用客戶賬戶返回餘額並更新客戶會話(就像保持活着)。
問題是,當客戶在同一時間要求爲getBalance兩次,而不是一個總是拋出一個異常,即使在保存(),我們有failOnError:假(和推杆嘗試捕捉周圍沒有幫助,見下文) 。我們需要refreshSession以默默的方式失敗,如果其他人當前正在刷新會話,並返回帳戶餘額,就好像沒有任何錯誤。我們無法弄清楚如何在grails中做到這一點failOnError:false和try catch不工作,丟棄和刷新都沒有任何影響。
SessionService:
boolean refreshSession(Session aSession) {
if (aSession != null) {
aSession.lastUpdatedAt = new Date()
aSession.save(flush:true, failOnError: false) // line 569. This always fails on error even with failOnError set to false.
return true
}
return false
}
這是我們得到的錯誤:
org.springframework.orm.hibernate4.HibernateOptimisticLockingFailureException: Object of class [com.xxx.Session] with identifier [23]: optimistic locking failed; nested exception is org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [com.xxx.Session#23]
at com.xxx.services.SessionService$$EQ2LbJCm.refreshSession(SessionService.groovy:569)
at com.xxx.getBalance(AccountController.groovy:56)
怎麼會失敗,如果failOnError =假?
會話服務是與否有關它沒有交易電學性能的研究定義的控制器稱爲:
控制器:
def getBalance() {
try {
:
Session session = sessionService.getSession(payload.token)
sessionService.refreshSession(session) // this updates the session object
def accountResult = accountService.getBalance(session.player) // line 59: this returns a structure of account domain objects
// which have a balance and currency etc. It is ready only!
render(status: 200, contentType: 'application/json') {
[
'result' : 0,
'accounts': accountResult.accounts
}
return
} catch (Exception e) {
renderError(ERROR, e.toString())
log.error("getBalance API Error:" + e.toString(), e)
}
我們曾嘗試:
- 使refreshSession事務性和非事務性(相同的結果)
- 從refreshSession中刪除「flush:true」。 (相同結果)
- 在刷新會話的身體周圍加入try catch(Exception e)。這沒有發現異常。 (相同結果)
- 在refresh會話體周圍添加try catch(Exception e)並創建refreshSession NotTransactional。
有趣的是,最後一個改變發生在到下一行異常的行(該一個讀取帳戶,其不寫入,僅讀出)
org.springframework.orm.hibernate4.HibernateOptimisticLockingFailureException: Object of class [com.xxx.Session] with identifier [23]: optimistic locking failed; nested exception is org.hibernate.StaleObjectStateException: Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect) : [com.xxx.Session#23]
at com.xxx.getBalance(AccountController.groovy:59)
嘗試丟棄()。沒有幫助。
@NotTransactional boolean refreshSession(Session aSession) { if (aSession != null) { try { aSession.lastUpdatedAt = new Date() aSession.save(failOnError: false) } catch (Exception e) { aSession.discard() aSession.refresh() } finally { return true } } return false }
用flush:true試過上面的問題。同樣的結果。
嘗試使refreshSession在自己的事務中獲取自己的會話副本。
@Transactional boolean refreshSession(long id) { Session session = Session.get(id) if (session != null) { try { session.lastUpdatedAt = new Date() session.save(flush: true, failOnError: false) } catch (Exception e) { println("XXX got exception:" + e.message) session.discard() } finally { return true } } return false }
這失敗,原始異常。在grails中忽略寫入失敗似乎是不可能的。即使異常被捕獲,並且它會打印出「XXX got exception」,異常再次拋出,原因不明。
我做的一切的理解是非交易它的工作原理就像自動提交:真正的 - 每一個DB更新會立即發生,如果一件事情失敗,它不會回滾其他的東西?
任何想法?
Session.withNewTransaction解決了它。我之前沒有看到過這個構造。另外,我曾假設,如果控制器不是跨國的,並且服務是交易,那麼服務將在該服務方法的持續時間內創建新的交易。我(和我所有的Grails同事)有多大錯誤。有沒有人找到一個博客或文檔來詳細說明交易如何在Grails中工作? –