2011-01-26 19 views
5

tôi nhận được ngoại lệ sau khi lưu một thể hiện của chuyến đi trong Grails:Grails Gorm: Object tham chiếu một thể hiện thoáng qua chưa được lưu

2011-01-26 22: 37: 42.801 [http-8090-5] ERROR errors.GrailsExceptionResolver - đối tượng tham chiếu một thể hiện thoáng qua chưa được lưu - lưu dụ thoáng qua trước khi xả nước: chèo thuyền org.hibernate.TransientObjectException: đối tượng tham chiếu một chưa được lưu thoáng dụ - lưu dụ thoáng trước khi xả nước: chèo thuyền

Khái niệm này rất đơn giản: Đối với một boattrip bạn cần một số tay chèo, một coxwain (cũng là một chèo thuyền) và một chiếc thuyền:

chuyến đi trông giống như (rút ngắn):

class Trip { 
    Boat boat; 
    Rower coxwain; 

    static belongsTo = [Rower,Boat] 
    static hasMany = [rowers:Rower] 
} 

và chèo thuyền (rút ngắn)

class Rower { 
    String firstname; 
    String name; 
    Rower reference; 

    static hasMany = [trips:Trip]; 
    static mappedBy = [trips:"rowers"] 
} 

chuyến đi sau đó được lưu trong bộ điều khiển như:

def save = { 
     def trip = new Trip(params) 

     // adding Rowers to Trip 
     if (params.rower instanceof String) { 
      def r = Rower.get(params?.rower) 

      if (r != null) { 
       trip.addToRowers(r) 
      } 
     } else { 
      params?.rower?.each{ 
       rowerid -> 
       def r = Rower.get(rowerid) 
       log.info("rowerid (asList): " + rowerid) 
       if (r != null) { 
        trip.addToRowers(r) 
       } 
      } 
     } 

     // saving the new Trip -> EXCEPTION IN NEXT LINE 
     if(!trip.hasErrors() && trip.save(flush:true)) { 
      // ... 
     } 
     // ... 
} 

Tôi nghĩ rằng tôi đã đặt mối quan hệ giữa các tên miền chính xác. Rower không thay đổi khi nó được thêm vào Trip. Tại sao Grails lại muốn nó cứu? tại sao nó là một ví dụ thoáng qua?

+0

Liệu nó xảy ra ở cả hai khối điều khiển (ví dụ: nếu và người khác)? –

+0

Bạn có nhận được thông báo đăng nhập nào không? –

Trả lời

0

Tôi nghĩ bạn phải lưu chuyến đi trước khi thêm xe tải vào chuyến đi. Cũng không có ý nghĩa gì nếu kiểm tra chuyến đi có lỗi trước khi bạn xác thực và/hoặc lưu nó không.

Hãy thử điều này:

if(trip.validate() && trip.save(flush:true)) { 
    if (r != null) { 
     trip.addToRowers(r) 
    } 
} 
0

Lúc đầu, tôi nghĩ rằng nó là để làm với tầng tiết kiệm và belongsTo, như mô tả trong The Grails Reference phần 5.2.1.3 và Gorm Gotchas part 2. Tuy nhiên kể từ khi Rowers đã có trong DB tôi nghĩ rằng nó sẽ làm việc. Mô hình miền phức tạp với tôi, những gì bạn cần làm là đơn giản hóa nó và chạy một số thử nghiệm bằng cách sử dụng bảng điều khiển Grails (chạy bảng điều khiển grails trong thư mục dự án của bạn). Trước tiên, tạo một cơ sở nhiều-nhiều giữa Trip và Rower và làm cho nó thực thi mã mong muốn. Sau đó, thêm các phần khác theo từng bit, giống như tham chiếu của Rower cho chính nó. Tôi không chắc chắn rằng phần mappedBy là cần thiết ở tất cả.

1

Sự cố bằng cách nào đó khác. nó ở đây:

def trip = new Trip(params) 

mà tham chiếu đến một coxwain (của lớp chèo thuyền), mà không được thiết lập (id = -1 được trả lại). Điều này xây dựng một Rower mới thay vì một giá trị 'null'. Và đây là 'ví dụ thoáng qua chưa được lưu'. Nếu tôi kiểm tra trước cho một phiên bản hợp lệ, thì nó hoạt động :-)

Cảm ơn sự giúp đỡ!

6

Thật không may đây là một vấn đề với cách GORM xử lý mọi thứ, hoặc cụ thể hơn là cách mà nó mong đợi rằng bạn đối phó với transients. Nếu bạn không duy trì các lớp được chứa trong cơ sở dữ liệu trước (Rowers trong trường hợp này), bạn sẽ nhận được ngoại lệ này mỗi lần duy nhất.

Với GORM bạn phải lưu và đính kèm theo kiểu dưới lên hoặc khi grails đi để xóa kết nối cho trường hợp tiếp theo, bạn sẽ nhận được trường hợp ngoại lệ tạm thời. Ví dụ là 'thoáng qua' vì nó chỉ là tham chiếu trong bộ nhớ. Để duy trì cha mẹ, GORM cần liên kết cha mẹ với đứa trẻ trong cơ sở dữ liệu. Nếu không có đứa trẻ được tiếp tục tồn tại nó không có cách nào để làm điều đó, đây là nơi mà các ngoại lệ đến từ.

Chúc bạn có tin tốt hơn. Không phải là khó khăn của nó, nhưng nó được gây phiền nhiễu với hệ thống phân cấp phức tạp.

1

Chỉ cần ghi chú nhanh cho bất cứ ai đối phó với các tham số số ít hay nhiều có cùng tên, sử dụng params.list("parameterName") helper bạn luôn có thể trả về một danh sách

... 

    // adding Rowers to Trip 
    if (params.rower instanceof String) { 
     def r = Rower.get(params?.rower) 

     if (r != null) { 
      trip.addToRowers(r) 
     } 
    } else { 
     params?.rower?.each{ 
      rowerid -> 
      def r = Rower.get(rowerid) 
      log.info("rowerid (asList): " + rowerid) 
      if (r != null) { 
       trip.addToRowers(r) 
      } 
     } 
    } 

    ... 

có thể trở thành một chút groovier

... 

    // adding Rowers to Trip 
    for(rower in params.list("rower") { 
     def r = Rower.get(rower) 
     if(r) trip.addToRowers(r) 
    } 

    ... 

bạn có thể tìm thấy nó ẩn đi dưới 6.1.12 Simple Type Converters

Các vấn đề liên quan