【问题标题】:EntityManager not fetching from database?EntityManager 没有从数据库中获取?
【发布时间】:2011-04-08 20:26:21
【问题描述】:

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

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

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

我有一个简单的页面,它显示单个帖子及其所有 cmets 和撰写它们的用户。 在底部我有简单的文本区域,当登录用户可以发表评论时。单击提交时,将调用来自支持 bean 的方法 saveComment。现在我键入评论单击提交操作 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())(基本上是return em.find(Post.class, id))不应该重新加载post,以便新评论可用吗?

在支持 bean 中也有 viewPost 操作,它执行相同的post = postBean.getPost(post.getId()),但似乎数据没有从数据库加载。我从数据库中删除了 cmets,但它们仍然列在 viewpost 页面中。

【问题讨论】:

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


    【解决方案1】:

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

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

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

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

    所以你需要在添加评论的时候正确设置所有双向关联的both

    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);
        }
    }
    

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

    无论如何,关键是设置关联的双方,您不必强制从数据库重新加载以“修复”您的对象图。

    【讨论】:

      【解决方案2】:

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

      我不确定,但我认为

      return "viewpost?faces-redirect=true";
      

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

      【讨论】:

      • 这是 JSF 2.0 的一部分。隐式导航。没有 faces-config 了。 ?faces-redirect=true 替换了旧式导航案例中的 &lt;redirect/&gt;
      • 您使用的是什么持久性提供程序?例如。在 eclipselink 中,您必须添加到 persistence.xml: 或命名查询:setHint(QueryHints.CACHE_USAGE, CacheUsage.DoNotCheckCache)。看这里:stackoverflow.com/questions/2809275/…
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-08-31
      • 1970-01-01
      • 2016-09-14
      • 1970-01-01
      • 2019-04-08
      • 2013-01-18
      相关资源
      最近更新 更多