0
votes

I'm relatively new to Hibernate.

Question is How to fetch both child objects and parent object when parent object is fetched; however during persistence time, persist only child object.

By the by, Foreign key is NOT associated at database level.

-------------------
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;
}

Works fine with below code

 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.
  }

However, fails if trying to persist only child Object.

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

I understand that it needs a parent object as reference, however, since business flow may not need a parent object and empty parentObject-row shouldn't persisted in DB, how this problem can be resolved?

1

1 Answers

0
votes

In bidirectional oneToMany relationship, the ,,many" side is whats called the owner of relationship. In your case the ChildObject entity. Owner of relationship is responsible for management of FK in database. Therefore your child objects must have its parent attribute filled correctly before it is persisted.
If you do not have a reference to parent for some reason, you need at least its Id, then you can load it and set it to your child instance. This is common scenario for REST api for example. Say you have an endpoint resource for creation of new child item for specific parent. In order to do that, you would probably do something like POST http://server/restapi/parent/12/children - insert new child at parent with id 12. In java you will get the child object, so you first fetch the parent by id and then simply set it to the child. This way the ORM is going to correctly represent the relationship in db.
You should also change the fetch type on parent.getChildobjects to Lazy in order to avoid N+1 issue and refactor your search method to explicitly fetch the children objects in a single query(instead of N as your current impl).
Happy hacking