I'm clearly struggling to understand this so help greatly appreciated...
I have the following mapping:
@Entity
@Table(name = "parent")
public class ParentEntity
{
...
@Id
@Column(name = "parent_id")
private Long id;
...
@OneToMany(mappedBy = "parent", fetch = FetchType.EAGER)
private List<ChildEntity> children;
...
}
@Entity
@Table(name = "child")
public class ChildEntity
{
...
@Id
@Column(name = "child_id")
private Long id;
...
@ManyToOne(fetch = FetchType.EAGER)
@NotFound(action = NotFoundAction.IGNORE)
@JoinColumn(name = "parent_id")
private ParentEntity parent;
...
}
in my db i have:
parent
------
parent_id: 1
child
------
child_id: 1, parent_id: 1
However
((Parent) session.get(Parent.class, 1)).getChildren()
returns null.
can anyone see what I have missing?
thanks, p.
EDIT
It seems to be more-so to do with session state in that the collection is not populated in the context of the same session, but the collection is populated in the next session...
consider the following:
void setupRender()
{
debug("existing not just added", (ParentEntity) session.get(ParentEntity.class, 13L));
ParentEntity parent = new ParentEntity();
session.save(parent);
ChildEntity child = new ChildEntity();
child.setParent(parent);
session.save(child);
debug("new one before commit", parent);
sessionManager.commit();
debug("new one after commit", parent);
debug("new one after re-fetch", (ParentEntity) session.load(ParentEntity.class, parent.getId()));
}
private void debug(String prefix, ParentEntity parent)
{
log.debug(prefix + ": parent id: " + parent.getId() + ", Children is "
+ (parent.getChildren() == null ? "null" : "size:" + parent.getChildren().size()));
}
results in the following output:
DEBUG - existing not just added: parent id: 13, Children is size:1
DEBUG - new one before commit: parent id: 23, Children is null
DEBUG - new one after commit: parent id: 23, Children is null
DEBUG - new one after re-fetch: parent id: 23, Children is null
so if it's due to session state, and commit isn't enough to trigger a re-fetch, what do I have to do to get the mapping to fetch the collection?
thanks again!
Yes, commit doesn't trigger refresh of the session cache.
The typical approach here is to use session-per-request pattern, so that you close the session immediately after commit, and open another session for the following transactions (though it's not an option if you use Open Session in View pattern).
Another good practice that may help to solve this problem is to modify both sides of bidirectional relationship simultaneously:
public class ParentEntity {
...
public void addChild(ChildEntity c) {
children.add(c);
c.setParent(this);
}
}
This way you can keep objects in the session cache in consistent state.
Finally, if you actually need to refresh an object inside a session you can call Session.refresh()
on it.
Adding cascade attribute as part of your OneToMany in parent entity might solve the problem.
@Entity
@Table(name = "parent")
public class ParentEntity
{
...
@Id
@Column(name = "parent_id")
private Long id;
...
@OneToMany(mappedBy = "parent", fetch = FetchType.EAGER, cascade=CascadeType.ALL)
private List<ChildEntity> children;
...
}
Then to persist the row
ParentEntity parent = new ParentEntity();
ChildEntity child = new ChildEntity();
child.setParent(parent);
parent.getChildren().add(child);
session.save(parent);
This will also delete all the children when deleting a parent.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With