2013-04-26 59 views
5

我被扔到一个现有的Grails项目和我遇到的问题之一是,节省一些批次时,我得到的错误:Cannot set readonly property: programIdGrails的“无法设置只读属性: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

+0

你的域对象中的'programId'在哪里?我可以看到'name','startDate','endDate','comments'和'currentStatus',但没有'programId' – 2013-04-26 14:08:03

+0

我不知道是否需要设置它,因为有一个belongsTo = [program:Program ]。 – Catfish 2013-04-26 14:09:24

+0

这不会给你一个'programId'。你将有一个'program.id',但你真的不想这样设置 – 2013-04-26 14:10:15

回答

12

programId是一个动态的属性,让你的program实例的ID,而无需从数据库中加载它,但它没有一个setter一个getter。如果你想设置,而不会产生加载整个实例的成本的基准,而不是使用:

batch.program = Program.load(120) 

load使用仅具有存储ID的代理,并且不访问数据库,除非你打电话一种方法或访问除id以外的其他财产。所以它会在这里工作,因为Hibernate只需要它的id用于最终运行的SQL插入。

0

另一个现实世界的方式与生成测试数据的插件将数据推到一个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导出生成的) - 在开发过程中,我在DB文件夹中的DataSource.groovy中使用dbCreate =“create-drop”吹掉数据库 - 所以这是一个简单的方法来重新创建它)。

的关键是:

continentLkp: ContinentLkp.load((it.column[1]).toLong()) 

其抓住文本ID,将其转换为长,并使用它用于ContinentLkp.load(),它是在用于CountryLkp域类构建()方法。噢,我将“_LoadData/db/country_lkp.xml”解析为.../YourGrailsProjectName/_LoadData/db/country_lkp.xml。花了我一段时间来弄清楚。

谢谢,伯特指出了这一点。