2012-03-02 27 views
37

tôi có một câu hỏi về tham khảo ParentEntities từ Child entites ir Nếu tôi có một cái gì đó như thế này:JPA @OneToMany -> mẹ - Reference Child (khoá ngoại)

Parent.java:

@Entity(name ="Parent") 
public class Parent { 
    @Id 
    @Generate..... 
    @Column 
    private int id; 

    @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY, mappedBy = "parent") 
    private Set<Child> children; 

    simple ... getter and setter ... 
} 

và Child.java:

@Entity(name ="Child") 
public class Child{ 
    @Id 
    @Generate.... 
    @Column 
    private int id; 

    @ManyToOne 
    private Parent parent; 

    ... simple getter an setter 
} 

Bàn Dưới đây là sẽ được tạo:

Parent: 
    int id 

Child: 
    int id 
    int parent_id (foreign key: parent.id) 

Ok, cho đến nay, mọi thứ vẫn ổn. Nhưng khi nói đến việc sử dụng tài liệu tham khảo này từ Java, tôi sẽ nghĩ, bạn có thể làm một cái gì đó như thế này.

@Transactional 
public void test() { 
    Parent parent = new Parent(); 

    Child child = new Child(); 
    Set<Child> children = new HashSet<Child>(); 
    children.add(child); 

    parent.setChildren(children); 
    entityManager.persist(parent); 
    } 

dẫn đến điều này trong cơ sở dữ liệu:

Parent: 
    id 
    100 

Child 
    id  paren_id 
    101 100 

Nhưng thats không phải là trường hợp, bạn phải explicity thiết Phụ Huynh cho trẻ em (trong đó, tôi sẽ nghĩ, khuôn khổ có thể có thể làm bằng cách chinh no).

Vì vậy, whats thực sự trong cơ sở dữ liệu là:

Parent: 
    id 
    100 

Child 
    id  paren_id 
    101 (null) 

nguyên nhân tôi đã không được thiết lập Phụ Huynh cho trẻ em. Vì vậy, Câu hỏi của tôi:

Tôi có thực sự phải làm sth hay không. như thế này?

Parent.java:

... 
setChildren(Set<Child> children) { 
    for (Child child : children) { 
    child.setParent.(this); 
    } 

    this.children = children; 
} 
... 

Edit:

Theo nhanh Trả lời tôi đã có thể để giải quyết vấn đề này bằng cách sử dụng các @JoinColumn trên Entity Reference-Sở hữu. Nếu chúng ta lấy ví dụ từ trên, tôi đã làm sth. như thế này:

Parent.java:

@Entity(name ="Parent") 
    public class Parent { 
     @Id 
     @Generate..... 
     @Column 
     private int id; 

     @OneToMany(cascade = CascadeType.ALL, fetch = FetchType.LAZY) 
     @JoinColumn(name= "paren_id") 
     private Set<Child> children; 

     simple ... getter and setter ... 
    } 

Và Child.java:

@Entity(name ="Child") 
public class Child{ 
    @Id 
    @Generate.... 
    @Column 
    private int id; 

    ... simple getter an setter 
} 

Bây giờ nếu chúng ta làm điều này:

@Transactional 
public void test() { 
    Parent parent = new Parent(); 

    Child child = new Child(); 
    Set<Child> children = new HashSet<Child>(); 
    children.add(child); 

    parent.setChildren(children); 
    entityManager.persist(parent); 
    } 

Các tham chiếu được thiết lập một cách chính xác bởi Cha mẹ:

Parent: 
    id 
    100 

Child 
    id  paren_id 
    101 100 

Cảm ơn câu trả lời.

+0

** bạn có cha mẹ trên thực thể con không? ** nếu có cách chúng được định cấu hình.Không có cha mẹ tôi nhận được lỗi (_StaleStateException: Cập nhật hàng loạt trả về số hàng không mong đợi từ bản cập nhật [0]; số hàng thực tế: 0; dự kiến: 1_). Nếu tôi thêm phụ huynh không có chú thích, nó cũng hiển thị lỗi (Lỗi ánh xạ). Với cài đặt @manytoone trên trường cha mẹ của con, tôi gặp lỗi khi lưu (_ORA-00904: "REPORT_REPORT_ID": недопустимый идентификатор_). fk của tôi và pk của nó trên id có tên report_id nhưng tôi không biết nơi report_report_id đến. – Erlan

+0

(Sử dụng EclipseLink JPA thực hiện). Cần lưu ý rằng bạn vẫn cần parenId dài @Column (name = "paren_id"); lập bản đồ cho con của bạn cho công việc này. – AfterWorkGuinness

Trả lời

12

Tôi có thực sự phải làm sth hay không. như thế này?

Đó là một chiến lược, vâng.

Trên các mối quan hệ hai hướng có một "sở hữu" và bên "không sở hữu" của mối quan hệ. Vì bên sở hữu trong trường hợp của bạn là trên Child, bạn cần đặt mối quan hệ ở đó để tiếp tục tồn tại. Phía sở hữu thường được xác định theo nơi bạn chỉ định @JoinColumn, nhưng có vẻ như bạn đang sử dụng chú thích đó, vì vậy, có thể phỏng đoán thực tế là bạn đã sử dụng mappedBy trong chú thích Parent.

Bạn có thể read a lot more about this here.

3

Vâng, đúng như vậy. JPA không quan tâm đến sự nhất quán của biểu đồ thực thể của bạn. Đặc biệt, bạn phải đặt nó ở phía chủ sở hữu của mối quan hệ hai chiều (trong trường hợp của bạn là thuộc tính cha của Child).

Trong JPA 2.0 điểm kỹ thuật này được nói với những lời sau đây:

Lưu ý rằng nó là ứng dụng đó phải chịu trách nhiệm cho duy trì tính nhất quán của thời gian chạy các mối quan hệ-ví dụ, cho đảm bảo rằng “một” và “nhiều ”Các bên của mối quan hệ giá thầu phù hợp với nhau khi ứng dụng cập nhật mối quan hệ khi chạy.

1

Chúng tôi gặp phải sự cố khi vẫn duy trì biểu đồ đối tượng đơn giản như biểu đồ được hiển thị ở trên. Chạy trong H2 mọi thứ sẽ hoạt động, nhưng khi chúng ta chạy với MySQL, "paren_id" trong bảng con (được định nghĩa trong chú thích @JoinColumn) không được phổ biến với id được sinh ra của cha - mặc dù nó được đặt là không -null cột với một ràng buộc khóa ngoại trong DB.

Chúng tôi muốn có được một ngoại lệ như thế này:

org.hibernate.exception.GenericJDBCException: Dòng 'paren_id' không có một giá trị mặc định

Đối với bất kỳ ai khác có thể chạy vào trong này, những gì cuối cùng chúng ta thấy được rằng chúng tôi đã đến một thuộc tính đến @JoinColumn để làm cho nó làm việc:

@JoinColumn (name = "paren_id", nullable = false)

0

Nếu tôi nhận bạn một cách chính xác, theo EntityManager, nếu bạn u muốn nó để quản lý thứ tự chèn của giao dịch của bạn phải "nói với anh ta" rằng nó nên vẫn còn trẻ em quá. Và bạn không làm điều đó, vì vậy "anh ấy" không biết những gì để tồn tại, nhưng danh sách con của cha mẹ bạn không có sản phẩm nào để "anh ấy" lấy nó có đúng nhưng giá trị được lưu trữ là không.

Vì vậy, bạn nên cân nhắc làm điều gì đó như:

... begin, etc 
em.persist(child) 
em.persist(parent) 

làm những gì bạn muốn với đối tượng phụ huynh ở đây sau đó cam kết và điều này sẽ làm việc đối với trường hợp tương tự như quá.

1

Dường như vẫn còn như vậy. Trong mẹ Entity bạn có thể có một cái gì đó giống như

@PrePersist 
private void prePersist() { 
    children.forEach(c -> c.setParent(this)); 
} 

để tránh lặp lại mã cho thiết lập mối quan hệ con/cha mẹ ở nơi khác trong mã.

+0

!! người đàn ông tốt đẹp sau khi tôi bị mắc kẹt alomost 2 tuần. tôi cố gắng gửi json từ khách hàng và chuyển đổi sang đối tượng bằng cách sử dụng @RequestBody của mùa xuân sau đó lưu vào db tôi không muốn quản lý quan hệ của tôi (đặt cha mẹ cho con - không có ý nghĩa đối với tôi) – WRDev

+0

!!! cập nhật !!! liên kết về @PrePersist (bạn có thể quản lý bởi @EntityListener) xem - https://www.concretepage.com/java/jpa/jpa-entitylisteners-example-with-callbacks-prepersist-postpersist-postload-preupdate-postupdate -preremove-postremove – WRDev

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