Я пишу форум, используя 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++;
}
}