2016-02-04 16 views
6

Tôi muốn tồn tại công ty mẹ với 20 đơn vị con, mã của tôi là dướiJPA Persist cha mẹ và con với một đến nhiều mối quan hệ

Lớp Chánh

@OneToMany(mappedBy = "parentId") 
private Collection<Child> childCollection; 

Child Lớp

@JoinColumn(name = "parent_id", referencedColumnName = "parent_id") 
@ManyToOne(optional=false) 
private Parent parent; 

String jsonString = "json string containing parent properties and child collection" 

ObjectMapper mapper = new ObjectMapper(); 
Parent parent = mapper.readValue(jsonString, Parent.class); 

public void save(Parent parent) { 
    Collection<Child> childCollection = new ArrayList<>() ; 

    for(Child tha : parent.getChildCollection()) { 
     tha.setParent(parent); 
     childCollection.add(tha); 
    } 

    parent.setChildCollection(childCollection); 
    getEntityManager().persist(parent); 
} 

Vì vậy, nếu có 20 bảng con thì tôi phải đặt tham chiếu cha mẹ ở mỗi trong số chúng cho rằng tôi phải viết 20 cho vòng lặp? Có khả thi không? là có cách nào khác hoặc cấu hình nơi tôi có thể tự động tồn tại cha mẹ và con?

+0

Điều này dường như có nhiều câu hỏi về JSON hơn câu hỏi JPA. Nếu JSON của bạn không được sắp xếp sao cho các mối quan hệ thích hợp được thiết lập, thì việc giữ cho trẻ tiếp tục khi lưu cha mẹ chỉ đơn giản là việc thêm các tùy chọn xếp tầng liên quan vào @OneToMany (giả sử ánh xạ của bạn là chính xác) –

+2

Nếu bạn không gửi con -> Quan hệ cha mẹ trở lại, hoặc nó không được thiết lập trong những gì được xây dựng từ JSON, sau đó có, bạn cần phải tự thiết lập nó trong mỗi thực thể con. Cách khác là làm cho mối quan hệ đơn hướng: loại bỏ mappedby = "parent" khỏi OneToMany và thay vào đó chỉ định một JoinColumn. Điều này sẽ làm cho OneToMany đặt khóa ngoài trong bảng con thay vì được đặt bởi tham chiếu của đứa con của nó (bạn nên loại bỏ thuộc tính cha mẹ và ánh xạ của con) – Chris

Trả lời

5

Fix lớp chuyên của bạn:

@OneToMany(mappedBy = "parent") 

mappedBy tài sản phải trỏ đến trường vào phía bên kia của mối quan hệ. Dưới dạng JavaDoc nói:

Trường sở hữu mối quan hệ. Bắt buộc trừ khi mối quan hệ là một chiều.

Ngoài ra bạn có explicitely nên kiên trì tổ chức Child trong chu kỳ:

for(Child tha : parent.getChildCollection()) { 
    ... 
    getEntityManager().persist(tha); 
    ... 
} 

Như Alan Hay nhận thấy trong bình luận, bạn có thể sử dụng cơ sở vật chất thác và để EntityManager tự động kéo dài tất cả các thực Child của bạn:

@OneToMany(mappedBy = "parent", cascade = CascadeType.PERSIST) 

Thông tin chi tiết về cascades (và JPA chính nó), bạn có thể tìm thấy trong Vlad Mihalcea's blog.

+0

Chẳng phải anh ta cũng cần tùy chọn xếp tầng này @OneToMany ? –

+0

nhưng đối với 20 bộ sưu tập con khác nhau, tôi sẽ phải viết 20 khác nhau cho các vòng? – Gora

+0

@Bharath Reddy, tôi nghĩ có, cos 20 bộ sưu tập con khác nhau là 20 đối tượng cha mẹ khác nhau và bạn sẽ gọi phương thức save (...) 20 lần. –

2

tôi sẽ cho phép phụ huynh kiên trì con riêng của nó

package com.greg; 

import java.util.ArrayList; 
import java.util.List; 

import javax.persistence.CascadeType; 
import javax.persistence.Column; 
import javax.persistence.Entity; 
import javax.persistence.FetchType; 
import javax.persistence.GeneratedValue; 
import javax.persistence.GenerationType; 
import javax.persistence.Id; 
import javax.persistence.JoinColumn; 
import javax.persistence.OneToMany; 

@Entity(name = "PARENT") 
public class Parent { 

    @Id 
    @GeneratedValue(strategy = GenerationType.AUTO) 
    private Long id; 

    @Column(name = "NAME") 
    private String name; 

    @Column(name = "DESCRIPTION") 
    private String description; 

    @OneToMany(cascade = CascadeType.ALL, fetch=FetchType.EAGER) 
    @JoinColumn(name = "parent", referencedColumnName = "id", nullable = false) 
    private List<Child> children = new ArrayList<Child>(); 

    public Long getId() { 
     return id; 
    } 

    public void setId(Long id) { 
     this.id = id; 
    } 

    public String getName() { 
     return name; 
    } 

    public void setName(String name) { 
     this.name = name; 
    } 

    public String getDescription() { 
     return description; 
    } 

    public void setDescription(String description) { 
     this.description = description; 
    } 

    public List<Child> getChildren() { 
     return children; 
    } 

    public void setChildren(List<Child> children) { 
     this.children = children; 
    } 

} 
2

Như đã chỉ ra trong các ý kiến, bạn phải chăm sóc các đối tượng đồ thị phù hợp với mối quan hệ con/phụ huynh. Tính nhất quán này sẽ không được giải phóng khi JSON đến trực tiếp từ tức là yêu cầu POST.

Bạn phải chú thích trường gốc và trường con với @JsonBackReference@JsonManagedReference.

lớp phụ huynh: lớp

@OneToMany(mappedBy = "parentId") 
@JsonBackReference 
private Collection<Child> childCollection; 

Child:

@JoinColumn(name = "parent_id", referencedColumnName = "parent_id") 
@ManyToOne(optional=false) 
@JsonManagedReference 
private Parent parent; 

câu hỏi tương tự với câu trả lời là here

Hơn nữa, nếu bạn sử dụng @JsonBackReference/@JsonManagedReference trên javax.persistence lớp chú thích kết hợp với Lombok của @ToString chú thích bạn sẽ gặp phải trong quá trình xoá kho lưu trữ r.

Chỉ cần loại trừ childCollectionparent trường từ @ToString chú thích với @ToString(exclude = ...)

Cùng sẽ xảy ra với Lombok của tạo equals() phương pháp (@Data, @EqualsAndHashCode). Chỉ cần thực hiện các phương thức đó bằng tay hoặc chỉ sử dụng các chú thích @Getter@Setter.

3

Nói chung, @JoinColumn chỉ ra rằng thực thể là chủ sở hữu của mối quan hệ & mappedBy chỉ ra rằng thực thể là nghịch đảo của mối quan hệ.

Vì vậy, nếu bạn đang cố gắng như sau

@OneToMany(mappedBy = "parent") 
private Collection<Child> childCollection; 

Điều đó có nghĩa là nó nghịch đảo của mối quan hệ và nó sẽ không đặt tham khảo mẹ sang con của nó.

Để đặt tham chiếu cha mẹ cho con của nó, bạn phải thực hiện đối tượng trên chủ sở hữu của mối quan hệ theo cách sau.

@OneToMany(cascade = CascadeType.ALL) 
@JoinColumn 
private Collection<Child> childCollection; 

Bạn không cần đặt bất kỳ tham chiếu con nào vì mã trên sẽ tạo cột trong bảng con.

+0

nó không phải là một cách tốt hơn vì nó được gọi là "OneToMany @ OneToMany' và sau đó Hibernate sẽ tạo thêm gấp đôi yêu cầu SQL cho DB https://vladmihalcea.com/2017/03/29/the-best-way-to-map-a-onetomany-hiệp hội-với-jpa-và-hibernate / – panser

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