6

我被扔进了一个现有的 grails 项目,我遇到的一个问题是,当批量保存一些东西时,我得到了错误:Cannot set readonly property: 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

4

2 回答 2

12

programId是一个动态属性,它为您提供实例的 id 而program无需从数据库中加载它,但它是一个没有 setter 的 getter。如果您想设置引用而不产生加载整个实例的成本,请改用:

batch.program = Program.load(120)

load使用仅存储 id 的代理,除非您调用方法或访问除id. 所以它会在这里工作,因为 Hibernate 只需要它id用于最终运行的 SQL 插入。

于 2013-04-26T14:22:08.693 回答
0

另一种将 Burt Beckwith 的答案与将数据推送到 MySQL 表中的 Build-test-data 插件一起应用的真实方法是这样的:

//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 生成的 - 在开发过程中,我让数据库被 dbCreate = "create-drop" 在 DataSource .groovy 在 conf 文件夹中 - 所以这是重新创建它的简单方法)。

关键是:

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

它获取文本 ID,将其转换为 Long 并将其用于 CountryLkp 域类的 build() 方法中的 ContinentLkp.load()。哦,我的“_LoadData/db/country_lkp.xml”解析为.../YourGrailsProjectName/_LoadData/db/country_lkp.xml。我花了一段时间才弄清楚。

谢谢,伯特指出这一点。

于 2014-01-08T16:28:06.490 回答