2013-04-26 7 views
5

mi hanno buttato in un progetto graal esistente e una delle questioni che sto avendo è che durante il salvataggio di qualcosa di un batch, ottengo l'errore: Cannot set readonly property: programIdGrails "Non posso impostare la proprietà di sola lettura: programId"

Ecco la mia risparmiare frammento che causa l'errore

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

Ecco il mio gruppo classe dominio

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 

    } 
} 

Perché non mi permetta di impostare il programId?

+0

Dove si trova 'programId' nell'oggetto dominio? Riesco a vedere 'name',' startDate', 'endDate',' comments' e 'currentStatus', ma non' programId' –

+0

Non ero sicuro se avessi bisogno di impostarlo dato che esiste un belongs = [program: Program ]. – Catfish

+0

Questo non ti darà un 'programId'. Avrai un 'program.id', ma in realtà non vuoi essere impostato come questo –

risposta

12

programId è una proprietà dinamica che fornisce l'ID dell'istanza program senza caricarlo dal database, ma è un getter senza setter. Se si desidera impostare il riferimento, senza sostenere il costo di caricare l'intera istanza, utilizzare questo invece:

batch.program = Program.load(120) 

load utilizza un proxy che ha solo l'ID memorizzato, e non va al database a meno che non si chiama un metodo o accedere a una proprietà diversa da id. Quindi funzionerà qui poiché Hibernate ha bisogno solo del suo id per l'inserto SQL che alla fine viene eseguito.

0

Un altro modo MONDO REALE di applicare la risposta di Burt Beckwith con il plugin Build-test-dati spingendo dati in una tabella di MySQL è come questo:

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

Sopra, sto leggendo i dati di ricerca Paese da un file xml (che è stato generato da un'esportazione XML da PhpMyAdmin da una tabella di ricerca country correttamente costruita - durante lo sviluppo ho il DB spazzato via con dbCreate = "create-drop" in DataSource.groovy nella cartella conf - quindi questo è un modo semplice per ricrearlo).

La chiave è:

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

che afferra l'ID del testo, lo converte in lungo e lo utilizza per la ContinentLkp.load(), che è nel metodo build() per la classe di dominio CountryLkp. Oh, e io "_LoadData/db/country_lkp.xml" risolve in .../YourGrailsProjectName/_LoadData/db/country_lkp.xml. Mi ci è voluto un po 'per capirlo.

Grazie, Burt per averlo indicato.

Problemi correlati