JPA坚持有一对多关系的父母和孩子

Gor*_*ora 18 jpa one-to-many

我想用20个子实体来持久保存父实体,我的代码如下

家长班

@OneToMany(mappedBy = "parentId")
private Collection<Child> childCollection;
Run Code Online (Sandbox Code Playgroud)

儿童班

@JoinColumn(name = "parent_id", referencedColumnName = "parent_id")
@ManyToOne(optional=false)
private Parent parent;
Run Code Online (Sandbox Code Playgroud)
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);
 }
Run Code Online (Sandbox Code Playgroud)

所以,如果有20个子表,那么我必须在每个子表中设置父引用,因为我必须写20个for循环?这可行吗?有没有其他方式或配置,我可以自动坚持父母和孩子?

Iva*_*nin 10

修复您的父类:

@OneToMany(mappedBy = "parent")
Run Code Online (Sandbox Code Playgroud)

mappedBy属性应指向关系另一侧的字段.正如JavaDoc所说:

拥有这种关系的领域.除非关系是单向的,否则是必需的.

你也应该在周期中明确地持久化子实体:

for(Child tha : parent.getChildCollection()) { 
    ...
    getEntityManager().persist(tha);
    ...
}
Run Code Online (Sandbox Code Playgroud)

正如Alan Hay在评论中注意到的那样,您可以使用级联设施并让EntityManager自动保留所有Child实体:

@OneToMany(mappedBy = "parent", cascade = CascadeType.PERSIST)
Run Code Online (Sandbox Code Playgroud)

关于级联(和JPA本身)的更多细节,你可以在Vlad Mihalcea的博客中找到.


mar*_*571 7

通常,@ JoinColumn表示实体是关系所有者, mappedBy表示实体是关系反转.

所以,如果你想跟随

@OneToMany(mappedBy = "parent")
private Collection<Child> childCollection;
Run Code Online (Sandbox Code Playgroud)

这意味着它与关系相反,并且不会为其子项设置父引用.

要设置对其子项的父引用,您必须按以下方式创建关系的上述实体所有者.

@OneToMany(cascade = CascadeType.ALL)
@JoinColumn
private Collection<Child> childCollection;
Run Code Online (Sandbox Code Playgroud)

您不需要设置任何子引用,因为上面的代码将在子表中创建一个列.


s17*_*net 5

正如评论中指出的那样,您必须注意对象图与子/父级关系的一致性。当JSON直接来自POST请求时,这种一致性就不会免费。

你必须标注与父和子场@JsonBackReference@JsonManagedReference

家长班:

@OneToMany(mappedBy = "parentId")
@JsonBackReference
private Collection<Child> childCollection;
Run Code Online (Sandbox Code Playgroud)

子班:

@JoinColumn(name = "parent_id", referencedColumnName = "parent_id")
@ManyToOne(optional=false)
@JsonManagedReference
private Parent parent;
Run Code Online (Sandbox Code Playgroud)

答案类似的问题在这里

此外,如果在带注释的类上使用@JsonBackReference/ @JsonManagedReferencejavax.persistence与Lombok的@ToString注释结合使用,则会发生stackoverflow错误。

只需从注释中排除childCollectionparent字段即可@ToString@ToString( exclude = ...)

同样将与龙目岛的产生发生equals()法(@Data@EqualsAndHashCode)。只需手动实现这些方法或仅使用@Getter@Setter注释即可。