2012-10-31 18 views
14

Câu hỏi của tôi ở đây gần giống với câu hỏi khác của tôi Explicit delete on JPA relationships nhưng tôi đã nghĩ đơn giản hóa việc này để đảm bảo các câu trả lời chi tiết hơn.Tại sao việc hợp nhất không bị xếp chồng lên mối quan hệ một đến nhiều

Hãy tưởng tượng tôi có mối quan hệ OneToMany giữa cha mẹ và con.

@Entity 
public class Parent { 
    private String name; 
    @OneToMany(mappedBy="owner",cascade=CascadeType.ALL, fetch=FetchType.EAGER) 
    private List<Child> children; 
} 
@Entity 
public class Child { 
    private String name; 
    @ManyToOne 
    private Parent owner; 
} 

Trong giao diện người dùng của tôi, tôi hiển thị danh sách phụ huynh. Người dùng có thể chọn một phụ huynh và họ có thể chỉnh sửa danh sách các con của họ. Để hiển thị điều này, tôi đã sử dụng biến currentParent để đại diện cho phụ huynh hiện tại được chỉnh sửa. Người dùng có thể chọn thêm/chỉnh sửa tên của trẻ em.

Khi nhấp vào một nút, tôi sẽ lưu danh sách trẻ em mới bằng cách sử dụng cuộc gọi EJB.

@ViewScoped 
public class MyBean(){ 
    private Parent currentParent; 
    @EJB 
    private MyEJB myEJB; 

    public void saveChanges(){ 
     myEJB.save(currentParent); 
    } 
} 

Cuộc gọi EJB của tôi trông như thế này.

@Stateless 
public class MyEJB{ 
    @PersistenceContext(unitName = "MyPU") 
    private EntityManager em; 

    public void save(Parent parentNew){ 
     Parent pOld = em.find(entityClass, p.getId()); 
     if(pOld !=null){ 
      pOld.setName(parentNew.getName()); 
      pOld.setChildren(parentNew.getChildren()); 
      em.merge(pOld); 
     } 
    } 
} 

Vấn đề của tôi là, tôi có thể thay đổi tên của cha mẹ nhưng bất kỳ thay đổi nào đối với danh sách trẻ em không được phản ánh trong DB. Nó không thay đổi hoặc thực thi bất kỳ SQL nào để xóa/cập nhật/thêm các child.

Nguyên nhân có thể là gì?

Cập nhật:

Vâng sau khi một số dùng thử và và đọc qua lỗi liên kết khác nhau, có vẻ như thiết lập tùy chọn orphanRemoval trong @onetomany tôi sẽ giải quyết vấn đề của tôi. Eclipselink tự động xóa các hàng mồ côi trong quá trình hợp nhất.

Vì vậy, nhiều cho JPA phức tạp ..

@Entity 
public class Parent { 
    private String name; 
    @OneToMany(mappedBy="owner",cascade=CascadeType.ALL, fetch=FetchType.EAGER,orphanRemoval = true) 
    private List<Child> children; 
} 
+0

Có thể điều này sẽ giúp: http://stackoverflow.com/questions/10656765/handling-collection-updates-with-jpa – JMelnik

+0

Xin chào, tôi không chắc chắn nếu tôi nhận được câu trả lời từ liên kết đó, vì vậy bạn có nghĩa là tôi có để lặp qua các bộ sưu tập và lưu nó từng người một? Tôi thực sự nghĩ rằng eclipselink sẽ xử lý việc tiết kiệm bộ sưu tập của tôi? Vì vậy, ví dụ tôi có 5 trẻ em trong một thực thể, và sau đó tôi chỉnh sửa nó chỉ với hai con, khi tôi gọi hoạt động hợp nhất, nó sẽ chăm sóc xóa/thêm các hàng. Cảm ơn –

Trả lời

1

Câu hỏi của bạn What could be the cause?. Nguyên nhân là nội dung giá trị của parentNew. Nếu parentNew là một trong những nguyên nhân sau, nó sẽ không ảnh hưởng/cập nhật cho trẻ.

  1. Không có trường hợp tham chiếu cha mẹ và thị thực vise con. --->Nó sẽ ném ngoại lệ.
  2. Parent giá trị tham số có danh sách rỗng hoặc trống là Clild ->Đây sẽ là nguyên nhân của bạn.
  3. Child không nhận được tên cập nhật từ giao diện người dùng .-->Đây sẽ là nguyên nhân của bạn.

Ví dụ. Tôi nhanh chóng viết nó. Không sao.

Đã tồn tại dữ liệu trong DB

Parent      Child 
================== ======================================= 
'P001', 'Parent 1' 'C002', 'Child 2', 'P001' 
        'C003', 'Child 3', 'P001' 
        'C001', 'Child 1', 'P001' 

Sau Upldated:

Parent      Child 
==================   ======================================= 
'P001', 'Update Parent 1' 'C002', 'Update Child 2', 'P001' 
          'C003', 'Update Child 3', 'P001' 
          'C001', 'Update Child 1', 'P001' 

List<Child> clidList = new ArrayList<Child>(); 
Parent parent = new Parent("P001", "Update Parent 1", clidList); 
Child c1 = new Child("C001", "Update Child 1", parent); 
Child c2 = new Child("C002", "Update Child 2", parent); 
Child c3 = new Child("C003", "Update Child 3", parent); 
clidList.add(c1); 
clidList.add(c2); 
clidList.add(c3); 

Parent existingParent = em.find(Parent.class, parent.getId()); 
existingParent.setName(parent.getName()); 
existingParent.setChildren(parent.getChildren()); 
em.merge(existingParent); 
5

Đây là vấn đề tiêu chuẩn với hợp nhất. Thay đổi đối tượng con trong bộ sưu tập sẽ được chọn.

Cuộc gọi hợp nhất chỉ có thể xếp chồng lên các đối tượng nằm trong danh sách, do đó thay đổi đối tượng không có trong danh sách bị mất. Thật không may, oneToMany không sở hữu mối quan hệ: ManyToOne của trẻ thực hiện. Vì vậy, các thực thể con cần được hợp nhất để thay đổi được nhìn thấy và được đẩy vào cơ sở dữ liệu. Các thực thể con là các đối tượng độc lập và cần được hợp nhất riêng lẻ khi chúng được thay đổi. Điều đó, hoặc được thêm vào một phụ huynh/cây khác để được hợp nhất.

+0

Xin cảm ơn thông tin, vì vậy bạn đề nghị tôi nên làm gì? –

+1

Bất kỳ số lượng tùy chọn nào. Người ta sẽ thêm họ vào một phụ huynh khác nếu có thể. Hoặc nếu họ không thể độc lập với cha mẹ của họ, hãy đánh dấu họ bằng việc loại bỏ trẻ mồ côi để họ bị xóa khi bị hủy đăng ký. Hoặc xử lý sự khác biệt trong bộ sưu tập trong cuộc gọi kết hợp cho phụ huynh bằng cách tìm cha mẹ đầu tiên và sửa trẻ em bị thiếu từ đối tượng được truyền để hợp nhất - điều này thậm chí có thể thực hiện được trong sự kiện. hoặc chỉ cần đảm bảo ứng dụng gọi hợp nhất trên trẻ em mà ứng dụng sẽ xóa khỏi cha mẹ. – Chris