Grails “圣杯”;无法设置只读属性:programId";

Grails “圣杯”;无法设置只读属性:programId";,grails,Grails,我被扔进了一个现有的grails项目,我遇到的一个问题是,当在批处理中保存某个内容时,我得到一个错误:无法设置只读属性:programId 下面是导致错误的保存代码段 // Create a batch def batch = new Batch() batch.name = session.batch_name batch.startDate = new Date() batch.endDate = new Date() batch.programId = 120 if(batch.save(

我被扔进了一个现有的grails项目,我遇到的一个问题是,当在批处理中保存某个内容时,我得到一个错误:
无法设置只读属性:programId

下面是导致错误的保存代码段

// Create a batch
def batch = new Batch()
batch.name = session.batch_name
batch.startDate = new Date()
batch.endDate = new Date()
batch.programId = 120
if(batch.save()) {
  ...
}
这是我的批处理域类

class Batch  extends AbstractDomainObject{
    String name
    Date startDate
    Date endDate
    String comments
    StatusType currentStatus

    static belongsTo = [program:Program]    

    static constraints = {
        name(blank:false,maxSize:100)
        startDate()
        endDate()
        comments (nullable:true, maxSize:DEFAULT_SIZE_OF_COMMENTS)
        currentStatus(nullable:true)
    }
    static transients= ["currentStatus"]

    static mapping = {
        id column:'batch_id', generator:'sequence', params:[sequence:'sq_batch']
        currentStatus column:'status_type_id'
        program column:'program_id'
        statuses sort:'statusDate'
        startDate type:'date'
        endDate type:'date'
    }

    public String toString(){
        return name
    }


    public Date createdDate(){
        Date date=null
        if(this?.statuses?.size()>0){
            this?.statuses.each{
                if(it.status.value==SystemConstants.STATUS_PENDING){
                    date = it.statusDate
                }
            }
        }
        return date

    }
}

为什么不让我设置
programId

programId
是一个动态属性,它在不从数据库加载的情况下为您提供
程序
实例的id,但它是一个没有setter的getter。如果要设置引用而不产生加载整个实例的成本,请改用此选项:

batch.program = Program.load(120)

load
使用只存储id的代理,除非调用方法或访问除
id
以外的属性,否则不会转到数据库。因此,它在这里可以工作,因为Hibernate只需要它的
id
就可以运行最终运行的SQL insert。

另一种在现实世界中应用Burt Beckwith的答案的方法是使用构建测试数据插件将数据推送到MySQL表中,如下所示:

//IMPORT THE COUNTRIES
    xmlRead = new XmlSlurper().parse("_LoadData/db/country_lkp.xml") //pulls out of .../TouchSourceWeb/_LoadData.... folder

    //println "Parsed country_lkp.xml OK"
    allRecs = xmlRead.database.table
    //println "size: " + allRecs.size()

    allRecs.each {
        com.touchsource.ts4.CountryLkp.build(continentLkp: ContinentLkp.load((it.column[1]).toLong()), countryName: it.column[2], isoContinentCode2: it.column[3], isoCountryCode: it.column[4])
  }
上面,我从一个xml文件中读取国家查找数据(该文件是由PhpMyAdmin从一个正确构建的国家查找表中导出的xml生成的——在开发过程中,我在conf文件夹的DataSource.groovy中使用dbCreate=“create drop”将DB吹走了——因此这是一种简单的重新创建方法)

关键是:

continentLkp: ContinentLkp.load((it.column[1]).toLong())
它获取文本ID,将其转换为Long,并将其用于ContinuLKP.load(),后者位于CountryLkp域类的build()方法中。哦,我把“\u LoadData/db/country\lkp.xml”解析为…/YourGrailsProjectName/\u LoadData/db/country\lkp.xml。我花了一段时间才弄明白


感谢Burt指出这一点。

域对象中的
programId
在哪里?我可以看到
名称
开始日期
结束日期
注释
当前状态
,但没有
程序ID
,我不确定是否需要设置它,因为有belongsTo=[program:program]。这不会给你
程序ID
。您将有一个
program.id
,但您确实不希望这样设置,因此我不能通过执行
batch.program.id
,在批处理表中显式设置程序id?