简体   繁体   English

注释映射双向OneToMany / ManyToOne没有提取?

[英]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. 返回null。

can anyone see what I have missing? 任何人都能看到我失踪的东西吗?

thanks, p. 谢谢,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 ). 这里的典型方法是使用每个请求的会话模式,以便在提交后立即关闭会话,并为以下事务打开另一个会话(尽管如果在View模式中使用Open Session,则不是一个选项)。

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. 最后,如果您确实需要在会话中刷新对象,则可以在其上调用Session.refresh()

Adding cascade attribute as part of your OneToMany in parent entity might solve the problem. 在父实体中添加级联属性作为OneToMany的一部分可能会解决问题。

@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 ) 以下是关于该主题的官方Hibernate指南:(摘自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. 在参考文档的第16章中有一个关于“父/子关系”的详细部分,包括代码示例。

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. 我不确定这是不是一个好习惯,但它很有效。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM