Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Grails "Cannot set readonly property: programId"

Tags:

grails

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?

like image 333
Catfish Avatar asked Apr 26 '13 13:04

Catfish


1 Answers

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.

like image 102
Burt Beckwith Avatar answered Oct 23 '22 19:10

Burt Beckwith