Показывать дерево сообщений как в живом журнале (Java) - PullRequest
2 голосов
/ 27 ноября 2011

Я пишу форум, используя Spring MVC + Hibernate.Hibernate использует ленивую инициализацию, и чтобы она работала, я использую OpenSessionInViewInterceptor, и она работает.Не должно быть никаких проблем с отложенной инициализацией.Я пытаюсь показать дерево сообщений, как это сделано в ответах в журнале.У меня есть только id, parentId, текстовые столбцы.

mysql> select * from posts;
+----+----------+----------+----------+--------+------------+----------+
| id | threadId | authorId | parentId | text   | created    | modified |
+----+----------+----------+----------+--------+------------+----------+
|  1 |        5 |     NULL |     NULL | fda    | 2011-11-24 | NULL     |
|  2 |        5 |     NULL |     NULL | aff    | 2011-11-24 | NULL     |
|  3 |        5 |     NULL |     NULL | faee   | 2011-11-24 | NULL     |
| 13 |        6 |     NULL |     NULL | f52    | 2011-11-26 | NULL     |
| 14 |        6 |     NULL |       13 | c431   | 2011-11-26 | NULL     |
| 15 |        6 |     NULL |     NULL | c31c13 | 2011-11-26 | NULL     |
| 16 |        6 |     NULL |       15 | n754   | 2011-11-26 | NULL     |
| 23 |        4 |     NULL |     NULL | v52    | 2011-11-26 | NULL     |
| 24 |        4 |     NULL |       23 | v53    | 2011-11-26 | NULL     |
| 25 |        4 |     NULL |     NULL | v423   | 2011-11-26 | NULL     |
| 26 |        4 |     NULL |       24 | v523   | 2011-11-26 | NULL     |
| 27 |        4 |     NULL |       23 | v253   | 2011-11-26 | NULL     |
+----+----------+----------+----------+--------+------------+----------+

Класс POJO Сообщение:

@Entity
@Table(name="posts")
public class Post{
    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
private Integer id;
@ManyToOne(cascade=CascadeType.REFRESH,fetch=FetchType.LAZY)
@JoinColumn(name="threadId")
private Thread thread;
@Column(name="authorId")
private Integer authorId;
@ManyToOne(cascade=CascadeType.REFRESH,fetch=FetchType.LAZY)
@JoinColumn(name="parentId")
private Post parentPost;
@Column(name="text")
private String text;
@Column(name="created")
private Date created;
@Column(name="modified")
private Date modified;
....Many getters and setters....
}

Я написал пользовательский тег JSP:

<custom:tree postList="${posts}"/> 

posts - список сообщений для этой темы.

My customTags.tld:

...    
<tag>
<description>message tree</description>
<name>tree</name>
<tag-class>forum.tag.MessageTree</tag-class>
<body-content>empty</body-content>

<attribute>
    <name>postList</name>
    <required>true</required>
    <rtexprvalue>true</rtexprvalue>
</attribute>
</tag>
...

И класс для этого пользовательского тега:

public class MessageTree extends SimpleTagSupport{
private List<Post> postList;
private StringBuffer output = new StringBuffer("<ul>");
public void setPostList(List<Post> postList){
    this.postList = postList;
}
public void doTag()throws JspException,IOException{
    retrieveOutput(null);
    output.append("</ul>");
    getJspContext().getOut().print(output.toString());
}
private void retrieveOutput(Integer parentId){
    int j = 0;
    while(j<postList.size()){
        if(parentId==null && postList.get(j).getParentPost()==null){
            output.append("<li>Id: "+postList.get(j).getId());
            output.append("<ul>");
            //retrieveOutput(postList.get(j).getId());
            output.append("</ul></li>");
        }else{
            if(postList.get(j).getParentPost().getId().equals(parentId)){ // !!!Here it throws java.lang.NullPointerException!!!!
                output.append("<li>Id: "+postList.get(j).getId());
                output.append("<ul>");
                retrieveOutput(postList.get(j).getId());
                output.append("</ul></li>");
            }
        }
        j++;
    }
}
}

И он выбрасываетисключения при проверке if (postList.get (j) .getParentPost (). getId (). equals (parentId))

java.lang.NullPointerException
forum.tag.MessageTree.retrieveOutput(MessageTree.java:31)
forum.tag.MessageTree.retrieveOutput(MessageTree.java:28)
forum.tag.MessageTree.doTag(MessageTree.java:18)
org.apache.jsp.WEB_002dINF.jsp.showThread_jsp._jspx_meth_custom_005ftree_005f0(showThread_jsp.java:457)
org.apache.jsp.WEB_002dINF.jsp.showThread_jsp._jspService(showThread_jsp.java:239)
org.apache.jasper.runtime.HttpJspBase.service(HttpJspBase.java:70)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
org.apache.jasper.servlet.JspServletWrapper.service(JspServletWrapper.java:433)
org.apache.jasper.servlet.JspServlet.serviceJspFile(JspServlet.java:389)
org.apache.jasper.servlet.JspServlet.service(JspServlet.java:333)
javax.servlet.http.HttpServlet.service(HttpServlet.java:722)
org.springframework.web.servlet.view.InternalResourceView.renderMergedOutputModel(InternalResourceView.java:238)
org.springframework.web.servlet.view.AbstractView.render(AbstractView.java:250)
org.springframework.web.servlet.DispatcherServlet.render(DispatcherServlet.java:1047)
org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:817)
org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:644)
org.springframework.web.servlet.FrameworkServlet.doGet(FrameworkServlet.java:549)
javax.servlet.http.HttpServlet.service(HttpServlet.java:621)
    javax.servlet.http.HttpServlet.service(HttpServlet.java:722)

Но когда я пытаюсь, например,

public void doTag()throws JspException,IOException{
    output.append(postList.get(1).getParentPost().getId());
    getJspContext().getOut().print(output.toString());
}

Работает и возвращает 23!Может быть, я делаю это абсолютно неправильно?Что вы можете посоветовать?

Ye, я обнаружил ошибки!Я переписал это немного.Проблема заключалась в том, что я не проверял в предложении else, есть ли у объекта пост-пост или нет.

private void retrieveOutput(Integer parentId){
    int j = 0;
    while(j<postList.size()){
        if(parentId==null && postList.get(j).getParentPost()==null){
            output.append("<li>Id: "+postList.get(j).getId()+"<br/>ParentId: 0<br/>Text: "+postList.get(j).getText()+"<br/>Posted: "+postList.get(j).getCreated()+"<br/><a href=\"/forums/deletePost/"+postList.get(j).getThread().getId()+"\">Delete this shit</a>");
            output.append("<ul>");
            retrieveOutput(postList.get(j).getId());
            output.append("</ul></li>");
        }else{
            if(postList.get(j).getParentPost()!=null && postList.get(j).getParentPost().getId().equals(parentId)){
                output.append("<li>Id: "+postList.get(j).getId()+"<br/>ParentId: "+postList.get(j).getParentPost().getId()+"<br/>Text: "+postList.get(j).getText()+"<br/>Posted: "+postList.get(j).getCreated()+"<br/><a href=\"/forums/deletePost/"+postList.get(j).getThread().getId()+"\">Delete this shit</a>");
                output.append("<ul>");
                retrieveOutput(postList.get(j).getId());
                output.append("</ul></li>");
            }
        }
        j++;
    }
    }

1 Ответ

1 голос
/ 28 ноября 2011

Я думаю, что ваша проблема с отложенной выборкой, вы не можете получить доступ к отложенному извлеченному свойству вне транзакции, проверьте эту ссылку .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...