2017-08-14 141 views
0

我们最近从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 
     } 
    } 
} 

为什么失败事务服务中时,坚持任何想法,但是当注释被删除不罚款?

回答

0

通过升级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版本。