【问题标题】:Update Parent reference when adding to @ManyToOne [duplicate]添加到@ManyToOne时更新父参考[重复]
【发布时间】:2016-09-02 09:04:17
【问题描述】:

让我们假设一个简单的 1 Father -> n Children 实体关系(getters/setters 省略):

@Entity
public class Father {

    @Id
    @GeneratedValue
    private Integer id;

    @OneToMany(mappedBy="father", cascade=CascadeType.ALL)
    private List<Child> children = new ArrayList<>();

    ...
}

@Entity
public class Child {
    @Id
    @GeneratedValue
    private Integer id;

    @ManyToOne(cascade=CascadeType.ALL)
    private Father father;

    ...
}

现在尝试通过简单地将孩子添加到父亲来更新这种关系时,它不起作用,因为 Child.father 没有得到更新:

Child child = new Child();
// optionally persist child first, tried
father.getChildren().add(child);
...save father

我尝试使用不同的 CascadeTypes,但似乎无法自动更新 Child.father 引用。我知道传统的方法是使用“addChild”方法,但我想知道是否有自动的方法?

我的配置是 Spring Boot + JPA (Hibernate) + H2,自动创建到数据库。有趣的是,我发现一些博客帖子似乎和我在这里所做的完全一样,但对他们来说它是有效的,但对我来说却不是。奇怪。

【问题讨论】:

    标签: java hibernate jpa spring-data spring-data-jpa


    【解决方案1】:

    是的,但这不是故意的。我只是真正解释它,因为它可以解释你在那些博客文章中看到的内容。您可以通过删除mappedBy 并添加@JoinColumn 使@OneToMany 成为关系的拥有方。但是,这主要用于您没有反向引用的情况。如果您保留@ManyToOne,那么 Hibernate 将看到两个碰巧共享相同列的关系。然而,据我所知,它应该可以工作。

    我曾经看到一个不合理的参考,它可能会导致性能问题,但我再也找不到那个参考,所以我不确定。它会存在两个问题,哪种类型可以证明该选项的“这实际上不是您应该这样做”的性质:

    1. 在关闭事务/会话并从数据库重新加载子实体之前,不会更新父字段。
    2. 如果您以后决定实施二级缓存,它可能会改变您的代码逻辑。这是因为子实体可能有一段时间不会从数据库中重新加载,在此之前,父字段将为空。

    您可以使用动态代理和反射自己实现这一点,但您必须通过 DAO/存储库控制实体的创建以确保它们被代理。

    最后,我个人不会推荐它。年纪越大,越觉得应用程序中的黑魔法越少越好。

    【讨论】:

    • 感谢您的回答。这里的“问题”与其说是 JPA 行为,不如说是 Spring Data Rest 中的结果,它允许我 PUT 到 /father/X/children 集合 - 但在那里没有做任何事情,因为它正确添加到集合中,但是这个添加不会改变任何东西......
    • 啊,我认为将孩子添加到父亲的标准方法是 PUT /child/X/father。如果您需要批量添加孩子,本文提到了一种方法,您可以使用 uri-list stackoverflow.com/questions/25311978/…
    • 这对我来说几乎是行不通的,因为最后一步已经完成(子/评论已放入或修补到列表中,但这不会更新其父/帖子参考) .它适用于您的解决方法,但正如您所说,这可能不是一个好主意。所以要么我希望整个事情失败而不是看起来成功(204)或工作。
    • 我很困惑。你是说PUT/child/X/father(不是father/X/children)更新集合而不是父引用?这对我来说似乎非常违反直觉。如果有的话,我希望它更新父引用而不是集合。
    • 不,用{ "father" : "http://..." } 更新/children/x 有效,还没有用/children/x/father 尝试过。只有这种方式不起作用,但它返回 204,就好像它起作用了一样,这也是非常违反直觉的。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2012-12-23
    • 2014-01-27
    • 2015-01-20
    • 2020-08-04
    • 1970-01-01
    • 1970-01-01
    • 2011-05-05
    相关资源
    最近更新 更多