【问题标题】:List vs Set when adding a GORM domain class添加 GORM 域类时的 List vs Set
【发布时间】:2016-04-06 15:13:29
【问题描述】:

假设我有以下(高度简化的)GORM 域类:

class PhoneCall extends Interaction {
    Survey survey
}

class Survey {
    String campaignCode
    Integer clientId
    Boolean isDynamic
    List interactions

    static constraints = {
        campaignCode unique: true, nullable: false
        clientId nullable: true
        isDynamic nullable: true
    }

    static hasMany = [interactions: Interaction]
}

class Interaction {
    String clazz
    Instant dateCreated

    static constraints = {
    }

    static mapping = {
        tablePerHierarchy false
        autoTimestamp false
    }

    def beforeInsert() {
        dateCreated = Instant.now()
    }
}

我有以下简单的代码来设置这些类进行测试:

def survey = new Survey(campaignCode: "TEST", isDynamic: true).save(failOnError: true, flush: true)
def phoneCall = new PhoneCall(survey: survey, clazz: PhoneCall.name).save(failOnError: true)

这会失败并出现以下堆栈跟踪:

org.springframework.dao.DataIntegrityViolationException: could not insert: [uk.co.nttfundraising.onitfhi.domain.PhoneCall]; SQL [insert into phone_call (id) values (?)]; constraint [survey_id]; nested exception is org.hibernate.exception.ConstraintViolationException: could not insert: [uk.co.nttfundraising.onitfhi.domain.PhoneCall]
    at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:643)
    at org.springframework.orm.hibernate3.HibernateAccessor.convertHibernateAccessException(HibernateAccessor.java:412)
    at org.springframework.orm.hibernate3.HibernateTemplate.doExecute(HibernateTemplate.java:412)
    at org.springframework.orm.hibernate3.HibernateTemplate.execute(HibernateTemplate.java:339)
    at org.codehaus.groovy.grails.orm.hibernate.metaclass.SavePersistentMethod.performSave(SavePersistentMethod.java:56)
    at org.codehaus.groovy.grails.orm.hibernate.metaclass.AbstractSavePersistentMethod.doInvokeInternal(AbstractSavePersistentMethod.java:215)
    at org.codehaus.groovy.grails.orm.hibernate.metaclass.AbstractDynamicPersistentMethod.invoke(AbstractDynamicPersistentMethod.java:63)
    at org.codehaus.groovy.grails.orm.hibernate.HibernateGormInstanceApi.save(HibernateGormInstanceApi.groovy:196)

但是,如果我从Survey 中删除List interactions 行(将interactions 变成Set),一切正常。如果我使用SortedSet interactions 也没有问题,尽管生成的数据库模式似乎没有任何顺序概念,所以我不确定该解决方案。谷歌大多建议不要保存Survey(例如this blog post),但我试过这个没有用。

只有List 失败,它会导致插入PhoneCall 完全忽略我的Survey!怎么回事?

【问题讨论】:

    标签: grails grails-orm grails-domain-class


    【解决方案1】:

    使用List 的一个注意事项是,您添加到其中的项目在添加到List 之前不能是save()d。但更重要的是,在使用一对多关联时将项目添加到集合的正确方法是使用survey.addToInteractions(),请参阅addTo*()。但首先,您需要一个适当的关联......

    class PhoneCall extends Interaction {
        static belongsTo = [survey: Survey]
    }
    

    通过将Survey 属性替换为belongsTo,您将获得正确的bi-directional one-to-many association。然后,您可以像这样使用/测试它:

    def survey = new Survey(campaignCode: "TEST", isDynamic: true)
    
    survey.addToInteractions(new PhoneCall(survey: survey, clazz: PhoneCall.name))
    survey.save(failOnError: true, flush: true)
    

    请注意,PhoneCall 从未显式保存,PhoneCall.survey 也未显式分配。当调用survey.save() 时,所有这些都会得到处理。

    保存后,someSurvey.interactions[index].survey 将引用 someSurvey

    【讨论】:

      猜你喜欢
      • 2018-12-16
      • 1970-01-01
      • 2011-09-27
      • 1970-01-01
      • 2014-08-22
      • 2016-06-24
      • 2010-12-22
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多