Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

annotation mapping bidirectional OneToMany/ManyToOne not fetching?

Tags:

java

hibernate

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!

like image 996
pstanton Avatar asked May 11 '11 02:05

pstanton


2 Answers

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.

like image 199
axtavt Avatar answered Sep 19 '22 15:09

axtavt


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.

like image 22
Prasanna Avatar answered Sep 21 '22 15:09

Prasanna