当前位置: 首页 > 面试题库 >

Hibernate @OneToMany,具有mappedBy(父子)关系和缓存问题

商佑运
2023-03-14
问题内容

我很长一段时间以来一直遇到这个问题,我已经在网上和网上搜索了SO,但尚未找到解决方案。我希望你能在这方面帮助我。

我在两个实体之间有一个父子关系,如下所示:

@Entity
public class Parent {
    // ...

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

    // ...
}

@Entity
public class Child {
    // ...

    @ManyToOne(fetch = FetchType.LAZY)
    private Parent parent;

    // ...
}

关键是,当我创建一个新的子代并将其分配给父代时,父代已经在缓存中时不会更新。

 Parent parent = new Parent();
 em.persist(parent);

 // ...

 Child child = new Child();
 child.setParent(parent);
 em.persist(child);

 parent.getChildren().size(); // returns 0

我尝试使用@PreUpdate在持久保留子级时将其自动添加到父级,但是如果我们在2个不同的线程中有2个实体管理器(例如在JBoss中),问题仍然存在,直到我们调用
em.refresh(parent)

因此,问题是-是否有办法顺利消除问题并确保parent.getChildren()始终返回最新的孩子名单?


问题答案:

大多数ORM都将以这种方式运行。

缓存中的对象不会从数据库中更新(不需要额外读取)。还要将对象模型和持久性视为独立的。即保持对象模型与其自身一致,并且不依赖于持久性机制为您完成此操作。

因此,如果要将对象添加到集合中,请在“ setParent”代码中执行此操作。

实际上,在这种情况下,最佳实践是让关系的一方完成所有工作,而让另一方顺其自然。我也建议使用字段访问而不是方法访问​​,那样您可以更灵活地自定义方法。

向父方法添加名为addChild的方法

 public void addChild(Child child) {
    child.setParent0(this);
    getChildren().add(individualNeed);
 }

然后在Child中设置setParent:

public void setParent(Parent parent) {
   parent.addChild(child);
}

Child中的setParent0是child上的parent的属性stter。

public void setParent0(Parent parent) {
   this.parent = parent;
}

我还建议“ getChildren”方法返回一个不可变的集合,以便开发人员不会无意间不使用此方法(我在所有这些方法中都学到了硬道理)。

还有一件事,您应该在上面的代码中包含空检查代码和其他防御性内容,为清楚起见,我将其省略。



 类似资料:
  • 我有三个班,站点,GoupIP和IP 一个站点有一个或多个抱怨。GroupIP有一个或多个IP。 代码如下: 地点 群居 IP 在GroupIp课堂上,我得到: 在属性“ips”中,“映射者”值“groupip”无法解析为目标实体上的属性。 我的代码出了什么问题??

  • 当我试图使用ebean缓存系统(带有io.ebean:ebean-redis)读取@ManyTomany关系时,我遇到了一个异常。这是一个springboot应用程序。 我正在使用的版本: SpringBootVersion=2.4.3 MariaDbVersion=2.7.2 EBeanVersion=12.7.2 Flywayversion=7.7.0 BaseModel Java类: 文章J

  • 在使用Hibernate删除与子实体具有关系的JPA实体时,我遇到了一个问题,但是在使用EclipseLink而不是Hibernate作为JPA提供程序时,相同的代码可以正常工作。父实体上的批注是 当使用Hibernate时,它尝试将子实体上的join列设置为null,但由于该列不允许null而失败。使用EclipseLink时,它首先删除子实体,然后删除父实体,这是所需的行为。 我的问题是: 为

  • 我定义了具有@OneToOne双向关系的实体。 关系的所有者站点(子类): 其他站点(父类): 当我试图坚持有子集的父母(不坚持),然后我得到了例外 TransientPropertyValueException:对象引用未保存的临时实例-在刷新之前保存临时实例 这看起来可以理解。 但当我定义具有双向一对一/多对一关联的实体时,如: 此关系的所有者站点: 关系的另一面: 并尝试持久化具有子集合集(

  • 问题内容: Book,User和Review说,我正在构建具有复杂模型的应用程序。 评论包含书籍和用户ID。为了能够搜索至少包含一个评论的“图书”,我已将“图书”设置为“评论”的父级,并且具有这样的路由。但是,我还需要找到撰写包含某些短语的评论的用户。 是否可以同时将书和用户作为评论的父级?有没有更好的方法来处理这种情况? 请注意,我无法更改数据建模的方式/不愿意这样做,因为数据已从持久性数据库传

  • 问题内容: 我们有一个带有父子关系的表,希望对它进行排序。排序标准是这样的,以便在遍历结果时,与父ID匹配的行应该已经存在: 问题在于两个密钥都是字符串,因此按ID或PARENT_ID排序将无法解决问题。 问题答案: 对于Oracle,使用分层查询: