请查看以下Facelet代码段:
<rich:datatable value="#{myBean.products}" var="prod">
<rich:column rowspan="#{rowspan.calcHomePageProductRowspan(prod)}">
#{prod.name}
</rich:column>
<rich:column rowspan="#{rowspan.calcHomePageProductRowspan(prod)}">
#{prod.number}
</rich:column>
...
<rich:column rowspan="#{rowspan.calcHomePageProductRowspan(prod)}">
#{prod.somethingElse1}
</rich:column>
<rich:column rowspan="#{rowspan.calcHomePageProductRowspan(prod)}">
#{prod.somethingElse2}
</rich:column>
...
<rich:column rowspan="#{rowspan.calcHomePageProductRowspan(prod)}">
#{prod.somethingElse3}
</rich:column>
</rich:datatable>
在上面的代码中,我通过计算EL表达式来计算一个属性(这里是rowspan,但这并不重要,它可以是任何属性或值,所以请不要关注它)。如您所见,计算该值的方法将当前prod作为参数。
我在rowspan
Seam组件中进行了内部优化,并在HashMap中保留了所有已计算的产品值。因此,当在第二个rich:column
计算EL表达式时,rowspan
首先在HashMap中查找已经计算的值,并返回该值,而不是重新计算。
虽然再次重新计算更好,但我仍然需要调用Seam组件。有没有办法以某种方式只调用一次Seam组件,并以某种方式保留当前迭代的计算值?
类似于Java,就是在每次迭代时在循环内定义一个变量,并在整个迭代过程中重用它。
注意:我已经进行了其他面向Seam的优化,例如@BypassInterceptors,Seam组件位于EVENT范围内,因此不会发生分层查找等。
答案 0 :(得分:1)
有没有办法以某种方式只调用一次Seam组件,并以某种方式保留当前迭代的计算值?
当然,理论上。
但我不确定我完全理解你的问题。你在谈论哪个缝线组件? rowspan
?
如果是这样的话,那么是的,每当你调用它时它会被调用,这是有道理的。您正在遍历dataTable,并为您调用它的每一行。
如果不了解有关您要做的事情的更多细节,很难提出答案。代码慢吗?这就是你需要进一步优化的原因吗?
<强>更新强>
试试这个,虽然我不确定它是否有效
<rich:dataTable value="#{myBean.products}" var="prod">
<ui:param name="myrowspan" value="#{rowspan.calcHomePageProductRowspan(prod)}"/>
<rich:column rowspan="#{myrowspan}">
#{prod.name}
</rich:column>
</rich:dataTable>
第二次更新
因此,如果您不将代码更改为@ Out,@ Factory,@ Unwrap或类似代码,则每次运行时都会对其进行评估。这就是JSF的工作原理。
这就是为什么他们说你应该在你的getter中这样做,因为JSF会为每个JSF阶段调用它。
public List<Foo> getFoo() {
if(this.field != null) {
field = (List)entityManager.createQuery("from Foo").getResultList();
}
return this.field;
}
如果您没有缓存列表并检查null,那么JSF会在每个阶段和数据表中的每一行中访问数据库。
因此,这只是你必须忍受的事情。