gpt4 book ai didi

Grails REQUIRES_NEW 和 "Illegal attempt to associate a collection with two open sessions"

转载 作者:行者123 更新时间:2023-12-02 14:42:03 25 4
gpt4 key购买 nike

当使用 REQUIRES_NEW 注释在服务方法上创建新事务时,会启动一个新的 Hibernate session ,这会导致“非法尝试将集合与两个打开的 session 相关联”错误。只有在保存包含集合的域对象时才会发生此错误。我正在使用 Grails 2.3.11。

域对象:

class MyObject {
String str
Integer value = 1
List container
static hasMany = [container : MyCollection]
}

class MyCollection {
String name
static belongsTo = [obj: MyObject]
}

交易服务:

import grails.transaction.Transactional
import org.springframework.transaction.annotation.Propagation

@Transactional
class MyService {

def getMyObjectById(Long id) {
return MyObject.get(id)
}

def proxyStartStateMachine(MyObject obj) {
doStateMachine(obj)

if (obj.someInteger < 5) {
triggerStateMachineReentry(obj)
} else {
//obj.attach()
//obj.refresh()
obj.discard()
}
}

@Transactional(propagation = Propagation.REQUIRES_NEW)
def doStateMachine(MyObject obj) {
updateStr(obj, "test${obj.version}")
}

def updateStr(MyObject obj, String str) {
obj.str = str
obj.save() // generates Hibernate error "Illegal attempt to associate a collection with two open sessions"
}

def triggerStateMachineReentry(MyObject obj) {
obj.value++
obj.save()

proxyStartStateMachine(obj)
}
}

Controller 入口点:

class ApiController {
def myService

def index() { }

def stuff(Long id) {
def obj = myService.getMyObjectById(id)
myService.proxyStartStateMachine(obj)

render(status: 200, text: 'OK', contentType: "text/html")
}
}

此服务的预期行为是有 5 个不同的事务,其中 MyObject.value 从 1 更新到 2、2 到 3、3 到 4 和 4 到 5。当集合 MyObject.container 从域中删除时对象,它工作正常。

MySQL 日志:

2302 Query  SET autocommit=0
2302 Query update my_object set version=1, str='test0', value=1 where id=1 and version=0
2302 Query commit
2302 Query SET autocommit=1
2302 Query SET autocommit=0
2302 Query update my_object set version=2, str='test1', value=2 where id=1 and version=1
2302 Query commit
2302 Query SET autocommit=1
2302 Query SET autocommit=0
2302 Query update my_object set version=3, str='test2', value=3 where id=1 and version=2
2302 Query commit
2302 Query SET autocommit=1
2302 Query SET autocommit=0
2302 Query update my_object set version=4, str='test3', value=4 where id=1 and version=3
2302 Query commit
2302 Query SET autocommit=1
2302 Query SET autocommit=0
2302 Query update my_object set version=5, str='test4', value=5 where id=1 and version=4
2302 Query commit
2302 Query SET autocommit=1

但是,一旦将集合添加到域对象,在 MyService.updateStr() 中进行第一次保存时,它就会在 MyService 中失败。

我知道这是由于新事务而发生的,但这是此处必需的功能,以确保在状态机的每次迭代期间提交更改并且不会回滚。

最佳答案

我想我已经找到了解决方案。在创建新事务之前,需要使用 object.discard() 从 Hibernate session 中删除该对象。

如果其他人有其他解决方案,请随时提出建议。

关于Grails REQUIRES_NEW 和 "Illegal attempt to associate a collection with two open sessions",我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29485314/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com