6

I got thrown into an existing grails project and one of the issues i'm having is that when saving something a batch, i get the error: Cannot set readonly property: programId

Here's my save snippet that causes the error

// 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()) {
  ...
}

Here's my batch domain class

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

    }
}

Why does it not let me set the programId?

Burt Beckwith
  • 75,342
  • 5
  • 143
  • 156
Catfish
  • 18,876
  • 54
  • 209
  • 353
  • Where is `programId` in your domain object? I can see `name`, `startDate`, `endDate`, `comments` and `currentStatus`, but no `programId` – tim_yates Apr 26 '13 at 14:08
  • I wasn't sure if i needed to set it since there is a belongsTo = [program:Program]. – Catfish Apr 26 '13 at 14:09
  • That won't give you a `programId`. You'll have a `program.id`, but you really don't want to be setting that like this – tim_yates Apr 26 '13 at 14:10
  • So i can't just set the program_id in the batch table explicitly by doing `batch.program.id`? – Catfish Apr 26 '13 at 14:15

2 Answers2

12

programId is a dynamic property that gives you the id of the program instance without loading it from the database, but it's a getter without a setter. If you want to set the reference without incurring the cost of loading the whole instance, use this instead:

batch.program = Program.load(120)

load uses a proxy that only has the id stored, and doesn't go to the database unless you call a method or access a property other than id. So it will work here since Hibernate only needs its id for the SQL insert that eventually gets run.

Burt Beckwith
  • 75,342
  • 5
  • 143
  • 156
0

Another REAL WORLD way to apply the answer of Burt Beckwith with the Build-test-data plugin pushing data into a MySQL table is like this:

//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])
  }

Above, I'm reading the country lookup data from an xml file (that was generated by an XML export from PhpMyAdmin from a properly built country lookup table - during development I have the DB blown away with dbCreate = "create-drop" in DataSource.groovy in conf folder - so this is an easy way to re-create it).

The key is:

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

which grabs the text ID, converts it to Long and uses it for the ContinentLkp.load(), which is in the build() method for the CountryLkp domain class. Oh, and I the "_LoadData/db/country_lkp.xml" resolves to .../YourGrailsProjectName/_LoadData/db/country_lkp.xml. Took me awhile to figure that out.

Thanks, Burt for pointing this out.

Twelve24
  • 637
  • 7
  • 15