我有一个 index.xhtml
<c:forEach items="${postsBean.homePagePosts}" var="category">
#{category.name}
<c:forEach items="#{category.posts}" var="post">
#{post.postTitle}
#{post.user.userName}
#{post.rating}
#{post.totalReads}
</c:forEach>
</c:forEach>
一个名为PostsBean.java的托管 bean ,有一个homePagePosts()方法,该方法使用休眠从数据库中获取记录并返回一个列表
public List getHomePagePosts() {
session = helper.getSessionFactory().openSession();
session.beginTransaction();
System.out.println("method called "+ i++ +" times");
List posts;
List categoryList = new ArrayList();
HashMap<String, Object> categoryName = new HashMap<String, Object>();
String HQL = "from Posts as post where post.category= :category order by post.totalReads desc";
Query query = session.createQuery(HQL);
Posts post;
query.setString("category", TextitConstants.BUSINESS);
posts = query.list();
if (!posts.isEmpty()) {
categoryName.put("name", TextitConstants.BUSINESS);
categoryName.put("posts", posts);
categoryList.add(categoryName);
categoryName = new HashMap<String, Object>();
}
query.setString("category", TextitConstants.EDUCATION);
posts = query.list();
if (!posts.isEmpty()) {
categoryName.put("name", TextitConstants.EDUCATION);
categoryName.put("posts", posts);
categoryList.add(categoryName);
categoryName = new HashMap<String, Object>();
}
query.setString("category", TextitConstants.ENTERTAINMENT);
posts = query.list();
if (!posts.isEmpty()) {
categoryName.put("name", TextitConstants.ENTERTAINMENT);
categoryName.put("posts", posts);
categoryList.add(categoryName);
categoryName = new HashMap<String, Object>();
}
query.setString("category", TextitConstants.HEALTH);
posts = query.list();
if (!posts.isEmpty()) {
categoryName.put("name", TextitConstants.HEALTH);
categoryName.put("posts", posts);
categoryList.add(categoryName);
categoryName = new HashMap<String, Object>();
}
query.setString("category", TextitConstants.POLITICS);
posts = query.list();
if (!posts.isEmpty()) {
categoryName.put("name", TextitConstants.POLITICS);
categoryName.put("posts", posts);
categoryList.add(categoryName);
categoryName = new HashMap<String, Object>();
}
query.setString("category", TextitConstants.SKILLS);
posts = query.list();
if (!posts.isEmpty()) {
categoryName.put("name", TextitConstants.SKILLS);
categoryName.put("posts", posts);
categoryList.add(categoryName);
categoryName = new HashMap<String, Object>();
}
query.setString("category", TextitConstants.TECHNOLOGY);
posts = query.list();
if (!posts.isEmpty()) {
categoryName.put("name", TextitConstants.TECHNOLOGY);
categoryName.put("posts", posts);
categoryList.add(categoryName);
categoryName = new HashMap<String, Object>();
}
query.setString("category", TextitConstants.SPORTS);
posts = query.list();
if (!posts.isEmpty()) {
categoryName.put("name", TextitConstants.SPORTS);
categoryName.put("posts", posts);
categoryList.add(categoryName);
}
return categoryList;
}
问题是在渲染 index.xhtml 页面之前多次调用方法 postsBean.homePagePosts。它应该只被调用一次并将一个列表返回给 forEach 循环,然后 forEach 循环将迭代列表并显示结果......
以下是我发现在表格中运行具有可变数据量的网站的测试结果
- 5 条记录 = 26 次执行
- 4 条记录 = 22 次执行
- 3 条记录 = 16 次执行
- 2 条记录 = 10 次执行
- 1 条记录 = 7 次执行
- 0 条记录 = 1 次执行
可以清楚的看到方法的执行和数据库的记录数没有对称性
需要注意的一件事...我没有在方法 postsBean.homePagePosts() 中关闭 Hibernate 会话,因为如果我这样做了,EL #{post.user.userName}在会话关闭时会出现异常。(post.user 是 User 类的对象)