2010-02-01 34 views
7

Tôi có một tầng lớp phụ huynh với các lĩnh vực sau đây với tầng tùy chọn:Hibernate (JPA) cascade - lấy id từ con

public class Parent { 
    @OneToMany(mappedBy = "parent", cascade = CascadeType.ALL) 
    @Cascade(org.hibernate.annotations.CascadeType.DELETE_ORPHAN) 
    private final Set<Child> children = new HashSet<Child>(); 
    public addChild(Child child) { children.add(child); } 
} 

Trong ứng dụng của tôi, tôi muốn thêm một đứa trẻ và sau đó gọi JPA sáp nhập vào phụ huynh lớp học, tự động kiên trì con mới của tôi. Điều này tất cả các công trình, tuy nhiên, các tài liệu tham khảo trẻ em origional tôi chèn vào đối tượng cha mẹ của tôi đã thay đổi, có nghĩa là tôi không thể lấy ID của đứa con kiên trì của tôi. Có cách nào tôi có thể nói hibernate để tái sử dụng tài liệu tham khảo trẻ em cũ của tôi thay vì làm một cái mới? trong việc hợp nhất

Trả lời

1

Chỉ cần lấy ví dụ sáp nhập của bố mẹ:

parent = entityManager.merge(parent); 

Cập nhật:

Những gì bạn muốn là không thể. Hoặc bằng cách thủ công merge() đứa trẻ, và sau đó thêm nó vào phụ huynh, hoặc có được trường hợp con mới từ bộ sưu tập phụ huynh và sử dụng nó để thay thế.

+0

Tôi biết, nhưng sau đó tôi chỉ nhận được trường hợp đã hợp nhất của cha mẹ tôi. Tôi muốn các trường hợp sáp nhập của con tôi để lấy ID của nó. Ofcourse tôi có thể lấy phần tử cuối cùng từ các con của tôi, nhưng điều đó cực kỳ khó chịu. – Jeroen

+0

cần có chúng cũng như một phần của cha mẹ mới. – Bozho

+0

Tôi muốn thực hiện như sau: Trẻ em = new Child(); parent.addChild (con); service.saveParent (cha mẹ); // thực hiện những việc có tham chiếu con liên tục, ví dụ: child.getId(); – Jeroen

1

Đối với nhiều thao tác, Hibernate tạo ra một sự kiện có thể được nghe và một số mã hỗ trợ để nghe.

Nếu bạn đang sử dụng Spring kết hợp với Hibernate, ví dụ, bạn có thể đăng ký lớp org.springframework.orm.hibernate3.support.IdTransferringMergeEventListener làm trình nghe cho sự kiện hợp nhất của hibernate (từ tôi nghĩ spring-orm.jar) bằng cách đặt sau trong hibernate.cfg.xml của bạn (hoặc bất kỳ tập tin được tham chiếu trong thiết lập mùa xuân của bạn cho ngủ đông config):

<event type="merge"> 
     <listener class="org.springframework.orm.hibernate3.support.IdTransferringMergeEventListener"/> 
    </event> 

hoặc bằng cách thêm một bản đồ trong đậu sessionfactory của bạn:

<bean id="sessionFactory" 
      class="org.springframework.orm.hibernate3.LocalSessionFactoryBean" 
      p:dataSource-ref="dataSource"> 
    <property name="configLocation" value="WEB-INF/classes/hibernate.cfg.xml"/> 
    <property name="eventListeners"> 
      <map> 
        <entry key="merge"> 
          <bean class="org.springframework.orm.hibernate3.support.IdTransferringMergeEventListener"/> 
        </entry> 
      </map> 
    </property> 

Nếu bạn thực hiện một trong hai cách này, người nghe này phải đặt id trong đối tượng gốc. Nếu bạn không sử dụng Spring, có khả năng một cách để có được một người nghe được kết nối tương tự như một trong những điều này.

Tôi chưa thử nghiệm hành vi con bạn đang tìm kiếm, nhưng tôi chắc chắn rằng việc hợp nhất trên phụ huynh sẽ kích hoạt hợp nhất trên con để người nghe sẽ được gọi cho cả hai.

Thiết lập cho JPA có thể khác, nhưng tôi nghi ngờ điều đó là có thể và hy vọng điều này sẽ đưa ra manh mối.

+0

Tôi có thể thêm người nghe vào persistence.xml của mình Tuy nhiên bây giờ tôi nhận được một OptimisticLockException khi lưu một đối tượng với các phần tử xếp tầng – Jeroen

+0

OptimisticLockException được ném vì tôi đã khai báo một thuộc tính @Version trên mỗi mô hình miền của tôi. Cuối cùng tôi đã giải quyết được vấn đề này bằng cách mở rộng IdTransferringMergeEventListener và sao chép giá trị phiên bản của tôi Cảm ơn bạn đã chỉ cho tôi đúng hướng !! – Jeroen

+0

Rất vui vì nó đã giúp ích và tôi hy vọng điều đó không gây ra vấn đề ở nơi khác. Tôi đã không sử dụng điều này trong ngữ cảnh JPA và không biết tác động đầy đủ. –