JSF:绝对需要将昂贵的业务逻辑放在访问器方法中。如何避免称这个昂贵的BL倍数时间

时间:2011-05-16 19:29:31

标签: java jsf java-ee

这是我的困境,我知道在JSF中访问器方法会多次调用,因此我知道不要在访问器方法中放置昂贵的业务逻辑(如DB访问)。如果我必须将业务逻辑放入我的访问器中该怎么办?在这种情况下我该怎么办?以下是我的困境的高层次布局。 (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); 
    }
}

如您所见,inner dataTable接受item dataTable的outer生成其List。有没有办法以某种方式停止handleReplies()被多次调用,因为这个访问器方法访问DB。

2 个答案:

答案 0 :(得分:2)

如何使用HashMap创建视图范围的缓存?

类似的东西:

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

这样,视图范围的bean存储先前的请求结果,并在请求已经完成时返回它们。如果没有,则发出请求。最后,没有重复请求!

答案 1 :(得分:2)

您也可以让JPA执行延迟加载和缓存作业(使用适当的二级缓存)。

假设您的Comment实体看起来像这样

@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;

    // ...
}

您可以使用#{comment.children}(懒惰地)让孩子们进入<h:dataTable>