EntityManager не загружается из базы данных? - PullRequest
1 голос
/ 06 сентября 2010

У меня есть объекты: сообщение, пользователь, комментарий с двунаправленными отношениями:

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

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

У меня есть простая страница, которая отображает один пост и все его комментарии и пользователей, которые их написали. Внизу у меня есть простая текстовая область, когда авторизованный пользователь может оставлять комментарии. При нажатии кнопки «Отправить» вызывается метод 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, так что новый комментарий должен быть доступен?

Существует также действие viewPost в компоненте поддержки, который делает то же самое post = postBean.getPost(post.getId()), но опять-таки кажется, что данные не загружаются из базы данных. Я удалил комментарии из базы данных, но они все еще были перечислены на странице Viewpost.

Ответы [ 2 ]

2 голосов
/ 07 сентября 2010

Вам не нужно попадать в базу данных (с EntityManager#refresh(), EntityManager.find() не будет попадать в базу данных, если экземпляр post уже загружен в контексте постоянства), если вы правильно установили двунаправленные ассоциации.

Проблема в том, что вы этого не делаете, и ваш объектный граф нарушается после добавления комментария, поэтому возникает необходимость перезагрузить сообщение из базы данных (что на самом деле является обходным решением настоящей ошибки).

По сути, ваша модель выглядит следующим образом:

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

Это менее подвержено ошибкам, проще в использовании, легчечитать.

В любом случае, ключ состоит в том, чтобы установить обе стороны ваших ассоциаций, вам не нужно принудительно перезагружать базу данных, чтобы "исправить" ваш граф объектов.

0 голосов
/ 06 сентября 2010

Пост может быть кэширован. Что такое @ID в вашем сообщении? Если в кеше есть сообщение с указанным идентификатором, оно берется из кеша, а не из базы данных. Попробуйте отключить кеш.

Я не уверен, но я думаю

return "viewpost?faces-redirect=true";

не будет работать. Обработчик навигации JSF берет эту строку и проверяет, настроена ли она в faces-config.xml. Если его там нет, он присоединяет расширение по умолчанию (возможно, .xhtml) и пытается перенаправить на такую ​​страницу. Поэтому он, вероятно, пытается перенаправить вас на viewpost?faces-redirect=true.xhtml, который, очевидно, не существует.

...