【问题标题】:Hibernate JPA: How to fetch child objects when parent object is fetched; however persist only parent objectHibernate JPA:获取父对象时如何获取子对象;但是只保留父对象
【发布时间】:2017-11-23 08:22:29
【问题描述】:

我对 Hibernate 比较陌生。

问题是在获取父对象时如何同时获取子对象和父对象;但是在持久化期间,只持久化子对象。

外键在数据库级别关联。

-------------------
ParentObject.java
-------------------

private Integer internalId;
private Set<ChildObject> childObjects = new HashSet<>(0);
private Integer userId;

//associated Setters as well.

@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "InternalId", unique = true, nullable = false)
public Integer getInternalId() {
    return this.internalId;
}

@OneToMany(fetch = FetchType.EAGER, mappedBy = "parentObject")
public Set<ChildObject> getChildObjects() {
    return childObjects;
}


-------------------
ChildObject.java
-------------------

private Integer internalRecordId;
private Integer userId;
private ParentObject parentObject;

// associated setters and remaining getters.

@ManyToOne(fetch = FetchType.LAZY)
@JoinColumn(name = "userId", nullable = true)
public ParentObject getParentObject() {
    return parentObject;
}

@Id
@GeneratedValue(strategy = IDENTITY)
@Column(name = "InternalId", unique = true, nullable = false)
public Integer getInternalId() {
    return this.internalId;
}

下面的代码可以正常工作

 Scenario1:
  Criteria criteria = getCriteria(ParentObject.java);
  criteria.add(Restrictions.eq("internalId", 123);
   Collection result = new LinkedHashSet(criteria.list());
  List<ParentObject> resultSet = new ArrayList<>(result);

  for(ParentObject parentObj : resultSet) {

     parentObj.getChildObjects()  --> Getting all associated Child Objects.
  }

但是,如果尝试保留子对象,则会失败。

   ChildObject childObj = new ChildObject();
   childObj.setUserId(123456);
   getSession().save(childObj);

我知道它需要一个父对象作为参考,但是,由于业务流可能不需要父对象并且空的 parentObject-row 不应该在 DB 中持久化,如何解决这个问题?

【问题讨论】:

    标签: hibernate jpa


    【解决方案1】:

    在双向 oneToMany 关系中,",,many" 一侧是所谓的关系所有者。在您的情况下,ChildObject 实体。关系所有者负责管理数据库中的 FK。因此,您的子对象必须有它的在持久化之前正确填充父属性。
    如果由于某种原因您没有对 parent 的引用,您至少需要它的 Id,然后您可以加载它并将其设置为您的子实例。例如,这是 REST api 的常见场景。假设您有一个端点资源,用于为特定父项创建新的子项。为了做到这一点,你可能会做类似POST http://server/restapi/parent/12/children的事情——在id为12的父对象处插入新的子对象。在java中你会得到子对象,所以你首先通过id获取父对象,然后简单地将它设置为子对象.这样,ORM 将正确地表示 db 中的关系。
    您还应该将 parent.getChildobjects 上的获取类型更改为 Lazy 以避免 N+1 问题并重构您的搜索方法以在单个查询中显式获取子对象(而不是 N 作为您当前的 impl)。
    愉快的黑客攻击

    【讨论】:

    • @SrinivasLakshman 如果对您有帮助,请将答案标记为已接受。
    猜你喜欢
    • 2022-12-15
    • 2015-01-04
    • 1970-01-01
    • 2021-01-25
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-25
    • 2020-01-26
    相关资源
    最近更新 更多