EntityManager无法从数据库中获取?

时间:2010-09-06 16:30:25

标签: orm jpa jsf-2 java-ee-6 jpa-2.0

我有实体:帖子,用户,评论双向关系:

---------   1     *  ---------
| Post  | <--------> |Comment|
---------            ---------

---------  1      *  ---------
| User  | <--------> |Comment|
---------            ---------

我有一个简单的页面,显示单个帖子及其所有评论和编写它们的用户。 在底部我有简单的textarea登录用户可以发表评论。单击提交时,将调用方法saveComment from backing bean。现在我输入注释点击提交操作saveComment导航到同一页面。 saveComment看起来像这样:

String username = getLoginName();
if(username != null)
{
    User u = userBean.getUser(username);
    post = postBean.getPost(post.getId());
    comment.setPost(post);
    comment.setUser(u);
    commentBean.updateComment(comment);
    post = postBean.getPost(post.getId());
}
return "viewpost?faces-redirect=true";

viewpost看起来像这样:

<ui:define name="content">
    <h:outputText value="#{postController.post.title}"/>
    <br/>
    <h:outputText value="#{postController.post.body}"/>
    <br/>
    <h:dataTable value="#{postController.post.comments}" var="item">
        <h:column>
            <h:outputText value="#{item.body}"/>
            <br/>
            <h:outputText value="#{item.user.username}"/>
            <br/>
        </h:column>
    </h:dataTable>
    <h:form rendered="#{postController.loggedIn}">
    <h:inputTextarea value="#{postController.comment.body}"/>
    <h:commandButton value="Submit" action="#{postController.saveComment}"/>
    </h:form>
</ui:define>

但是,当我单击“提交”时,注释将保存到数据库中但不会呈现。基本上post = postBean.getPost(post.getId())的{​​{1}}不应该重新加载return em.find(Post.class, id),以便新评论可用吗?

在支持bean中也有viewPost操作执行相同的post,但同样看起来数据没有从数据库加载。我从数据库中删除了评论,但它们仍然列在了viewpost页面中。

2 个答案:

答案 0 :(得分:2)

如果适当地设置双向关联,则不应该访问数据库(使用EntityManager#refresh(),如果已在持久性上下文中加载了post实例,则EntityManager.find()将不会访问数据库) 。

问题是你没有,并且在添加评论后你的对象图被破坏了,因此需要从数据库重新加载帖子(这实际上是真正错误的解决方法)。

基本上,你的模型是这样的:

+-------+   1     *  +-------+  *      1  +-------+
| Post  | <--------> |Comment| <--------> |  User |
+-------+            +-------+            +-------+

因此,您需要在添加评论时正确设置所有双向关联的两个

String username = getLoginName();
if(username != null)
{
    User u = userBean.getUser(username);
    post = postBean.getPost(post.getId());

    post.getComments().add(comment);
    comment.setPost(post);

    u.getComments().add(comment);
    comment.setUser(u);

    commentBean.updateComment(comment);

    //post = postBean.getPost(post.getId()); // you should not have to do this
}
return "viewpost?faces-redirect=true";

“设置双向关联链接的两端”通常在实体的辅助方法中完成,例如在Post:

@Entitysamples
public class Post {
    ...
    public void addToComments(Comment comment) {
        this.comments.add(comment);
        comment.setPost(this);
    }
}

这不易出错,易于使用,更易于阅读。

无论如何,关键是要设置关联的两面,你不必强制从数据库重新加载来“修复”你的对象图。

答案 1 :(得分:0)

可以缓存帖子。你帖子里的@ID是什么?如果在缓存中存在具有指定标识的Post,则从缓存而不是从数据库获取。尝试禁用缓存。

我不确定,但我认为

return "viewpost?faces-redirect=true";

不起作用。 JSF导航处理程序接受此字符串,并检查它是否在faces-config.xml中配置。如果它不存在,它会附加默认扩展名(可能是.xhtml)并尝试重定向到此类页面。所以它可能会尝试将您重定向到显然不存在的viewpost?faces-redirect=true.xhtml