JSF: Absolutely need to put expensive Business Logic inside accessor method. How to avoid calling this expensive BL multiples time

落花浮王杯 提交于 2019-12-22 16:47:09

问题


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(comment); 
    }
}

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.


回答1:


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!




回答2:


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



来源:https://stackoverflow.com/questions/6022337/jsf-absolutely-need-to-put-expensive-business-logic-inside-accessor-method-how

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!