我被抛入现有的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
?
答案 0 :(得分:12)
programId
是一个动态属性,它为您提供program
实例的id而不从数据库加载它,但它是一个没有setter的getter。如果要设置引用而不产生加载整个实例的成本,请改为使用:
batch.program = Program.load(120)
load
使用仅存储了id的代理,除非您调用方法或访问id
以外的属性,否则不会访问数据库。所以它可以在这里工作,因为Hibernate只需要id
来最终运行的SQL插入。
答案 1 :(得分: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” “在conf文件夹中的DataSource.groovy中 - 所以这是重新创建它的简单方法。”
关键是:
continentLkp: ContinentLkp.load((it.column[1]).toLong())
获取文本ID,将其转换为Long并将其用于ContinentLkp.load(),它位于CountryLkp域类的build()方法中。哦,我的“_LoadData / db / country_lkp.xml”解析为... / YourGrailsProjectName / _LoadData / db / country_lkp.xml。我花了一些时间才弄明白。
谢谢,伯特指出这一点。