【发布时间】:2014-07-25 11:21:40
【问题描述】:
我有一个带有控制器的应用程序。执行控制器的操作会更新数据库字段。当一次完成一个动作时,它可以正常工作。但是当我同时做两个动作时,我得到了org.hibernate.StaleObjectStateException 错误
Row was updated or deleted by another transaction (or unsaved-value mapping was incorrect)
我需要控制器能够处理同时执行的操作,例如将请求排队并按顺序执行。这有可能吗?还是我需要自己处理?
(会在这里使用synchronized 帮助吗?这是正确的方式吗?)
数据库是内存/文件,因为我很少使用它。不需要运行完整的数据库。
编辑:调用“层次结构”如下:
这是入口点 - 控制器。
GameController
def doTurn() {
String login = params.login
// From stackoverflow
def c = Player.createCriteria()
def player = c.get {
eq "login", login
lock true
}
// def player = Player.findAllByLogin(login).get(0)
PlayerChoice choice = Utils.intToChoice(Integer.parseInt(params.choice))
int turnNumber = Integer.parseInt(params.turn)
gameFlowService.makeTurn(player, choice, turnNumber)
def res = new Utils().playerStateToJSON(player)
render res as JSON
}
它调用gameFlowService:
GameFlowService{
def makeTurn(Player player, PlayerChoice choice, int turnNumber) {
(...)
Game currentGame = player.currentGame
Turn lastTurn = currentGame.getLastTurn()
// I do stuff with Turn (if it exists) or create it
currentGame.createTurn()
currentGame.getLastTurn().makeChoice(player, choice)
if (currentGame!=null){
currentGame.save(flush: true, failOnError: true)
}
}
游戏:
Game {
Player player1
Player player2
int turnsToBePlayed
List turns
static hasMany = [turns: Turn]
static belongsTo = [tournament: Tournament]
public void createTurn() {
Turn turn = new Turn([game : this,
turnNumber: turns.size(),
player1 : player1,
player2 : player2,
choice1 : PlayerChoice.CHOICE_NOT_SET,
choice2 : PlayerChoice.CHOICE_NOT_SET,
points1 : 0,
points2 : 0])
this.addToTurns(turn)
this.save(flush: true, failOnError: true)
}
}
然后转身:
class Turn {
int turnNumber
boolean completed = false
Player player1
Player player2
PlayerChoice choice1
PlayerChoice choice2
int points1
int points2
static belongsTo = [game: Game]
public void makeChoice(Player player, PlayerChoice playerChoice){
// This method only changes Turn's member variables
}
}
我只在添加新回合时保存 Game 实例 - 我被引导相信 Hibernate 会自动保留任何进一步的更改。
尽管使用了锁,我仍然得到同样的错误(stacktrace 说它在游戏中在线发生:this.save(flush: true, failOnError: true))
编辑 2: 我相信我的问题并不少见。控制器操作会导致数据库发生变化,并且需要以某种方式进行序列化。 Hibernate/Grails 是如何解决的?
【问题讨论】:
-
显示一些 COOOOOOODDDDDEEEEE!
标签: database multithreading hibernate grails