开发者

annotation mapping bidirectional OneToMany/ManyToOne not fetching?

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 ChildEnti开发者_运维技巧ty();
    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.


In your original question it implied that the data already existed in the database before you open the session, this was a critical piece of information to know you save it in the same session...

Here is the official Hibernate guidance on that topic by the way: (taken from http://community.jboss.org/wiki/HibernateFAQ-CommonProblems)

I'm having trouble with a bidirectional association.

When you update a bidirectional association you must update both ends.

parent.getChildren().add(child);
child.setParent(parent);

It's best to do this in an association management method of your persistent class.

I'm still having trouble!

Read the documentation! There's a detailed section about "Parent/Child Relationships" in chapter 16 of the reference documentation including code examples.


The solution I use at the moment is to initialize the collection manually during construction:

private List<ChildEntity> children 
    = new ArrayList<ChildEntity>;

I'm not sure if that is a good practice, but it works and is simple.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜