开发者

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>.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜