更新II: 好吧,我设法将它缩小了一点。
我有一个带有数据表的页面,其中包含排序和过滤功能,这些都发生在数据库中。换句话说,我不使用我使用的rich:datatable的嵌入式功能,而是让数据库完成工作。
我使用请求范围的 bean。唯一的会话范围bean包含我的界面的排序和过滤。
每列的过滤都绑定到某些会话bean字段。因此,它实际上在更新模型值阶段更新。
排序需要我的部分逻辑,所以我调用某个方法来为会话bean设置正确的值。这是在Invoke Application阶段执行的。
因此,在渲染响应阶段,页面实际呈现的任何更改都已到位。
问题是我的页面中的JSF datatable和datascroller调用backingBean.getDataModel()
从数据库和dataModel.getRowCount()
获取数据(我已经实现了它来调用运行单独查询的方法)在应用请求值阶段,也。这两个查询也会在渲染响应阶段进行,渲染响应阶段是更改全部到位的唯一阶段,查询将正常运行。
这意味着在执行过滤或排序后显示页面时,会发生双倍的查询。
我想执行排序和过滤,只执行所需的查询而不再执行。
有什么建议吗?
答案 0 :(得分:1)
应用请求值阶段期间的getter调用是强制性的,因为JSF需要知道最初显示哪些输入值,以便它最终可以在适用的下一阶段进行任何验证和/或调用任何valuechangelisteners。还必须找出在任何行中按下/单击了哪个按钮/链接,以便它知道在调用操作阶段调用哪个bean操作。
但是如果你没有任何要验证/值更改检查的输入字段,也没有任何行中的任何按钮/链接,那么我可以想象在申请请求值阶段的查询完全在你眼中多余的。
不幸的是,你不能完全禁用它。从技术上讲,唯一的方法是将数据bean放在会话范围内,并且只在bean的构造函数和bean操作方法中执行昂贵的SQL查询(以及刷新datamodel),这样它才会在bean的bean中调用构造(用于第一个视图)和bean的动作方法(在新的排序/过滤器/任何请求期间)。然而,缺点是数据模型中的任何更改都反映在最终用户在同一会话中打开的所有窗口/选项卡中,这可能会导致“wtf?”最终用户的经历。
现在,Tomahawk是第一个对preserveDataModel
的{{1}}属性有一个很好的解决方法,它基本上将数据模型放在特定于请求的组件树中(依次为已存储在会话范围或客户端的隐藏输入字段中,具体取决于您在faces-config中配置视图状态的存储位置的方式。 RichFaces没有这样的直接解决方案,但<t:dataTable>
基本相同。它只会影响“整个”bean,因此如果您的数据bean包含的不仅仅是数据模型,您可以考虑重构它。您应该记住将bean设计为会话作用域bean。
如果数据模型变大,那么我可以想象这会影响服务器内存,但如果你只将数据模型的可查看部分存储在内存中,那么这应该不会造成太大的伤害(和因此不是整个数据模型,包括所有其他页面)。看看它是否超过了在单个HTTP请求期间触发双SQL查询的成本。
希望这有帮助。