2010-01-15 5 views
11

Câu hỏi này có hai phần, phần đầu tiên là về việc xóa danh sách và phần thứ hai là gán một chủ sở hữu cho một đối tượng.Làm cách nào để xóa và thay thế bộ sưu tập trong mối quan hệ một-nhiều trong Grails/Groovy

Tôi có mối quan hệ một-nhiều giữa hai đối tượng miền trong mô hình của tôi trong Grails. Mối quan hệ trông như thế này ...

class Person { 

    static hasMany = [authorities: Role, locations: Location] 
} 

class Location { 

    static belongsTo = Person 

} 

Trong ứng dụng của tôi danh sách locations trên Person được hoàn toàn làm mới và thay thế bằng một danh sách mới về một hành động người dùng. Hơn nữa, tôi nhận được danh sách các đối tượng Location độc lập với số Person được liên kết. Tôi giải quyết người nào để áp dụng chúng bằng cách truy xuất người dùng hiện đã đăng nhập, mà tôi gọi là activePerson và là tốt cho mục đích của tôi.

Điều tôi muốn làm là xóa tất cả các vị trí hiện tại trên activePerson và chèn tất cả các vị trí mới, liên kết chúng với activePerson khi tôi di chuyển. Tôi có một loạt các thuộc tính trên Person mà tôi không muốn tồn tại vào thời điểm này, vì vậy tôi muốn tránh lưu toàn bộ đối tượng cha mẹ chỉ vì vị trí trẻ em đã thay đổi.

Tôi đã nghĩ đến việc lặp lại danh sách activePerson.locations và xóa từng cái một và dựa vào GORM/Hibernate để nhóm các truy vấn lại với nhau và tuôn ra ở cuối. Điều này có vẻ như sức mạnh vũ phu, mặc dù nó có thể làm việc. Tôi đã mong đợi có một phương pháp clearLocations hoặc một cái gì đó tương tự, nhưng tôi không thể tìm thấy một.

Nếu tôi chỉ thay thế activePerson.locations bằng danh sách mới và gọi activePerson.save(flush:true), GORM có xử lý việc xóa các hàng hiện có không?

Thứ hai, tôi muốn đặt các đối tượng Location mới vào activePerson. Một lần nữa tôi có thể cư trú activePerson.locations và tiết kiệm toàn bộ điều, nhưng tôi muốn tránh điều đó nếu tôi có thể. Tôi có thể lưu chúng riêng lẻ, nhưng làm cách nào để đặt belongsTo trên mỗi đối tượng Location khi tôi đi?

Vì vậy, để tóm tắt:

  1. Làm thế nào để xóa một danh sách ở nhiều kết thúc của một bộ sưu tập một-nhiều?
  2. Làm cách nào để liên kết các đối tượng độc lập với đối tượng mẹ và duy trì chúng riêng lẻ?

Cảm ơn

Trả lời

8

Đối # 1 bạn có thể xóa bộ sưu tập (Đó là một tập theo mặc định):

activePerson.locations.clear() 

Đối # 2 addToLocations sử dụng:

activePerson.addToLocations(location) 

và khi bạn lưu người vị trí < -> mối quan hệ người sẽ được cập nhật.

+0

@Burt, cảm ơn (một lần nữa) vì câu trả lời của bạn, tôi nợ bạn một ly bia. Tuy nhiên, điều này có nghĩa là tôi phải kiên trì đối tượng Person, cái mà tôi đang cố tránh. Có một lựa chọn hợp lý hay tôi chỉ nên sống với việc cập nhật một bản ghi mà không thực sự thay đổi? – Simon

+0

Ngoài câu trả lời của Burt, bạn có thể cần phải thực hiện equals và hashcode trên đối tượng bộ sưu tập, và chỉ định cascade: "all-delete-orphan" trên bản đồ của bộ sưu tập. –

+2

'activePerson.locations.clear()' trên bộ sưu tập sẽ không hoạt động. Hãy thử: 'activePerson.locations.collect(). Mỗi {item.removeFromLocations (it)}' – Athlan

8

Xoá Collection cách tiếp cận không làm việc cho tôi:

activePerson.locations.clear() 

Chỉ cần cố gắng lặp qua bộ sưu tập với tránh ConcurrentModificationException bằng cách gọi collect():

activePerson.locations.collect().each { 
    item.removeFromLocations(it) 
} 

Và sau đó lưu các đơn vị để thực hiện câu lệnh SQL :

activePerson.save flush:true 

Liên kết đến bài viết để đọc thêm: http://spring.io/blog/2010/07/02/gorm-gotchas-part-2/

+0

nó không làm việc cho tôi cho đến khi tôi chỉ định orphanRemoval = true trên Entity @OneToMany (..., orphanRemoval = true) – Mahakala

+2

Không nên 'mục' là 'activePerson'? Vì vậy, theo cách đó chúng ta có thể gọi removeFromLocations (nó)? –

6

Trong khi đây là một câu hỏi cũ, tôi chạy vào một tình huống rất giống nhau trong đó tôi muốn cập nhật một bộ hồ sơ trẻ em. Đây là cách tôi chọn để giải quyết nó. Để đơn giản, tôi sẽ sử dụng cùng một tên đối tượng/quan hệ với tư cách là người hỏi câu hỏi.

  1. Trong mapping khối domain cha, thêm:

    static mapping = { 
        locations(cascade: "all-delete-orphan") 
    } 
    
  2. Trong lĩnh vực trẻ em, thêm @EqualsAndHashCode chú thích (chỉ trong trường hợp có một số khác rình rập về, tôi đề cập đến groovy.transform.EqualsAndHashCode).

  3. Thêm tất cả các phần tử con vào miền mẹ bằng cách sử dụng các phương pháp Grails addTo (ví dụ: addToLocations) và sau đó lưu tên miền gốc.

Trong khi phương pháp này không đòi hỏi phải tiết kiệm domain cha (mà hỏi không muốn làm), nó có vẻ như đó là cách tiếp cận thích hợp nhất cho rõ ràng belongsTo định nghĩa trong mô hình. Vì vậy, tôi sẽ trả lời câu hỏi đánh số của Người hỏi như thế này:

  1. Thay vì làm nó bằng tay, chúng ta hãy Grails/Hibernate xóa các hồ sơ bằng cách xác định hành vi all-delete-oprhan thác về mối quan hệ.

  2. Đừng cố lưu trực tiếp bản ghi con, nhưng thay vào đó lưu đối tượng mẹ để khớp với những gì Grails có vẻ mong đợi.