我们最近从Grails 2.2.4升级到3.2.2。从那以后,我们在试图用组合键持久化一个新创建的对象时遇到了问题。Grails 3 - 带复合键的域对象并不总是保存
比方说,我们有一个名为SomeField的域对象。
class SomeField {
static belongsTo = [parentClass : SomeParentClass]
static hasMany = [joinedFields : JoinedField]
joinedFields fetch:'join', cascade:'all-delete-orphan'
}
还有另一个名为JoinedField的域对象,它属于它的两个SomeField成员之一。它使用这两个字段来创建其组合键。
class JoinedField {
SomeField field1
SomeField field2
static belongsTo = [field1: SomeField]
static mapping = {
id composite: ['field1', 'field2']
columns {
field1 column:'F1_ID'
field2 column:'F2_ID'
}
version false
}
static contraints = {
field1(nullable:false)
field2(nullable:false)
}
def getPk = {
['field1':field1.id, 'field2':field2.id]
}
}
字段2总是已经存在于数据库中,并加入当它JoinedField对象被从那里抬头。
当field1的父项全部为新并且我们保存它时,field1被保存并且JoinedField对象按照预期与两个键一起保存。但是,当field1的父项已被保存时,然后将JoinedField对象添加到现有的field1对象或新的field1对象并保存后,JoinedField对象不会被保留。
例子:
someParent.addToFields(aRealField1)
def jf = new JoinedField()
aRealField1.addToJoinedFields(jf)
jf.field2 = SomeField.findById(1234)
someParent.save()
所以 - 如果aRealField1属于尚未保存,然后“aRealField1”父和“JF”当aRealField1的父对象被保存的持久化。如果field1的父项已经存在,那么当保存aRealField1的父项时,'jf'不会被保存,即使aRealField1没有被保存好。
我认为GORM并不认为这个对象是脏的,需要持久性,因为它是从两个现有对象创建的,即使它是由这两个现有对象组成的新对象。但我没有看到在这种情况下强制进行级联保存的方法。这一切都与Grails 2.2.4一起工作。
更新:
似乎有在这个心脏交易问题。我们有一个SomeParentClass控制器,用于接收请求以保存对象。这又会调用'withTransaction'闭包中的Transactional服务类,以便在出现任何错误时回滚事务。该服务会进行多次保存,并且我们希望保留在发生任何错误时能够回滚整个设备的能力。
如果我们删除服务上的@Transactional注释,并在控制器中关闭withTransaction,那么上面的JoinedField类可以很好地保存。但是,当发生错误时,我们缺乏整套更改的回滚。
我们已经删除了控制器中的withTransaction,并且可以在它仍然注释为Transactional时处理服务中的回滚,但是JoinedField对象仍然无法按所述持续存在。
例子: 代码只有在服务回滚是干净的:
import grails.transaction.Transactional
@Transactional
class BuildObjectService {
def buildObject(def json) {
try {
// build the object from json representation
}
catch(Exception e) {
transactionStatus.setRollbackOnly()
throw e
}
}
}
为什么失败事务服务中时,坚持任何想法,但是当注释被删除不罚款?