JSF: Absolutely need to put expensive Business Logic inside accessor method. How to avoid calling this expensive BL multiples time
Here is my dilemma, I know in JSF the accessor method will get call mutilple times, therefore I know not to put expensive business logic (like DB access) in accessor method. What if I absolutely have to put business logic into my accessor. What should I do in this case? Below are a high level layout of my dilemma. (Mojarra 2.1, GF 3.1)
<h:dataTable value="#{myBean.comments}" var="item1">
<h:column>
#{item1.name} says: #{item1.comment}
<h:dataTable value="#{myBean.handleReplies(item1)}" var="item2">
<h:column>
#{item2.name} replies: #{item2.comment}
</h:column>
</h:dataTable>
</h:column>
</h:dataTable>
@ManagedBean
@ViewScoped
public void myBean(){
private List<Comment> comments;
@EJB
private MyEJB myEJB;
@PostConstruct
public void init(){
comments = myEJB.getAllComments();
}
//getters and setters for List<Comment> comments
public List<Comment> handleReplies(Comment comment){
//Return a List of replies of the comment
return myEJB.getRepliesFromComment(c开发者_JS百科omment);
}
}
As you can see, the inner
dataTable take in the item
of the outer
dataTable to generate its List. Is there a way for somehow stop handleReplies()
to be called multiple times, since this accessor method access DB.
How about using a HashMap
to create a view-scoped cache?
Something like:
private Map<Comment, List<Comment>> replies = new HashMap<Comment, List<Comment>>();
public List<Comment> handleReplies(Comment comment){
if (!replies.containsKey(comment)) {
replies.put(comment, myEJB.getRepliesFromComment(comment));
}
return replies.get(comment);
}
This way, your view-scoped bean store previous request results, and returns them if the request has already been done. If it hasn't, the request is made. In the end, no duplicate request!
You can also just let JPA do the lazy loading and caching job (with a proper second level cache).
Assuming that your Comment
entity look like this
@Entity
@NamedQuery(name="Comment.list", query="SELECT c FROM Comment c WHERE c.parent IS NULL")
public class Comment implements Serializable {
@ManyToOne(optional=false)
private Comment parent;
@OneToMany(mappedBy="parent", fetch=LAZY, cascade=ALL);
private List<Comment> children;
// ...
}
You could just use #{comment.children}
to (lazily) get the children in a <h:dataTable>
.
精彩评论