我们最近从Grails 2.2.4升级到了3.2.2。从那时起,在尝试使用复合键持久存储新创建的对象时,我们一直遇到问题。
假设我们有一个名为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]
}
}
Field2始终已经存在于数据库中,并在其中添加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的父项时将保留'aRealField1'和'jf'。如果field1的父级已经存在,那么即使保存aRealField1也可以,但保存aRealField1的父级时不会保存'jf'。
我认为GORM不会将其识别为脏对象并需要持久性,因为它是由两个现有对象创建的,即使它本身是由这两个现有对象组成的新对象。但是在这种情况下,我看不出有办法强制进行这种级联保存。所有这些都与Grails 2.2.4一起使用。
更新:
似乎这是核心的交易问题。我们有一个SomeParentClass的 Controller ,在该 Controller 中接收到保存对象的请求。依次调用“withTransaction”闭包内的Transactional服务类,以允许我们在发生任何错误时回滚事务。该服务可节省大量费用,我们希望保留在发生任何错误时回退整个集合的功能。
如果我们删除服务上的@Transactional批注以及 Controller 中的withTransaction闭包,那么上面的JoinedField类将保存得很好。但是,当发生错误时,我们将缺乏对完整更改集的回滚。
我们已经删除了 Controller 中的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
}
}
}
关于为什么为什么在事务服务中这种方法无法持续但在删除该注释时仍能正常运行的任何想法?
最佳答案
通过将org.grails:grails-datastore-gorm *,org.grails:grails-datastore-core和org.grails.plugins:hibernate5升级到最新的6.1.6.RELEASE版本,解决了此问题。
这将替换org.grails:grails-depenedencies引入的6.0.3版本。
关于hibernate - Grails 3-具有复合键的域对象并不总是保存,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45683674/