2013-04-26 8 views
5

tôi bị ném vào một dự án grails hiện và là một trong những vấn đề tôi đang gặp là khi tiết kiệm một cái gì đó đợt một, tôi nhận được lỗi: Cannot set readonly property: programIdGrails "không thể đặt thuộc tính readonly: programId"

Dưới đây là tôi tiết kiệm đoạn gây ra lỗi

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

Dưới đây là hàng loạt lớp tên miền của tôi

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 

    } 
} 

Tại sao nó không cho phép tôi thiết lập các programId?

+0

'ProgramId' ở đâu trong đối tượng miền của bạn? Tôi có thể thấy 'name',' startDate', 'endDate',' comments' và 'currentStatus', nhưng không có' programId' –

+0

Tôi đã không chắc chắn nếu tôi cần thiết để thiết lập nó vì có một thuộc tính = [program: Program ]. – Catfish

+0

Điều đó sẽ không cung cấp cho bạn một 'programId'. Bạn sẽ có một 'program.id', nhưng bạn thực sự không muốn thiết lập như thế này –

Trả lời

12

programId là thuộc tính động cung cấp cho bạn id của phiên bản program mà không tải nó từ cơ sở dữ liệu, nhưng đó là trình khởi động mà không cần thiết lập. Nếu bạn muốn thiết lập các tài liệu tham khảo mà không phải gánh chịu chi phí tải toàn bộ ví dụ, sử dụng này để thay thế:

batch.program = Program.load(120) 

load sử dụng một proxy mà chỉ có id được lưu trữ, và không đi đến cơ sở dữ liệu, trừ khi bạn gọi một phương pháp hoặc truy cập vào một tài sản khác không phải là id. Vì vậy, nó sẽ làm việc ở đây kể từ khi Hibernate chỉ cần id của nó cho chèn SQL mà cuối cùng được chạy.

0

Một cách khác REAL WORLD để áp dụng các câu trả lời của Burt Beckwith với các plugin Build-test-dữ liệu đẩy dữ liệu vào một bảng MySQL là như thế này:

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

Ở trên, tôi đang đọc dữ liệu tra cứu nước từ một tệp xml (được tạo bởi một xuất XML từ PhpMyAdmin từ bảng tra cứu quốc gia được xây dựng đúng - trong khi phát triển tôi có DB bị thổi bay đi với dbCreate = "create-drop" trong DataSource.groovy trong thư mục conf - vì vậy đây là một cách dễ dàng để tạo lại nó).

Điều quan trọng là:

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

mà lấy ID văn bản, chuyển đổi nó để dài và sử dụng nó cho các ContinentLkp.load(), mà là ở phương pháp xây dựng() cho lớp miền CountryLkp. Ồ, và tôi "_LoadData/db/country_lkp.xml" giải quyết thành .../YourGrailsProjectName/_LoadData/db/country_lkp.xml. Đã cho tôi một thời gian để tìm ra điều đó.

Cảm ơn, Burt đã chỉ ra điều này.