请求范围的 bean 和数据模型初始化?
更新二: 好的,我设法缩小了范围。
我有一个带有数据表的页面,具有排序和过滤功能,两者都发生在数据库中。换句话说,我不使用我使用的 rich:datatable 的嵌入式功能,而是让 DB 来完成工作。
我使用请求范围 bean。唯一的会话范围 bean 包含我的界面的排序和过滤。
对每列的过滤都绑定到特定的会话 bean 字段。因此,它实际上是在更新模型值阶段更新的。
排序需要我的一些逻辑,因此我调用某种方法来为会话 bean 设置正确的值。这是在调用应用程序阶段执行的。
因此,任何更改都在页面实际呈现的渲染响应阶段进行。
问题是我页面中的 JSF 数据表和 datascroller 调用从数据库获取数据的 backingBean.getDataModel()
和 dataModel.getRowCount()
(我使用的已实现调用运行单独查询的方法)也在应用请求值阶段。这两个查询也会发生在渲染响应阶段,这是唯一一个更改全部到位且查询将正常运行的阶段。
这意味着要在执行过滤或排序后显示页面,会发生双倍的查询。
我只想执行排序和过滤,仅执行所需的查询,仅此而已。
有什么建议吗?
UPDATE II:
OK, I managed to narrow it down a little.
I have a page with a datatable with sorting and filtering functionalities, both taking place in the DB. In other words, I do not use the embedded functionality of the rich:datatable I use, but rather let the DB do the work.
I work with request-scoped beans. The only session-scoped beans contain the sorting and filtering of my interface.
Filtering for each column is bound to the certain session bean fields. As such, it is actually updated during the Update Model Values phase.
Sorting required some logic from my part, so I invoke a certain method to set the correct values to the session bean. This is performed during the Invoke Application phase.
So, any changes are in place during the Render Response phase, where the page actually renders.
The problem is that the JSF datatable and datascroller in my page call the backingBean.getDataModel()
that fetch the data from the DB and the dataModel.getRowCount()
(which I have implemented to invoke a method that runs a separate query) also during the Apply Request Values phase. These two queries take also place during the Render Response Phase, which is the only phase where the changes are all in place, and the query will run normally.
This means that to show a page after I perform filtering or sorting, the double number of queries take place.
I want to perform sorting and filtering only performing the required queries and no more.
Any suggestions?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
应用请求值阶段期间的 getter 调用是强制性的,因为 JSF 需要知道最初显示了哪些输入值,以便最终可以在下一阶段(如果适用)进行任何验证和/或调用任何 valuechangelistener。还必须找出在任何行中按下/单击了哪个按钮/链接,以便它知道在调用操作阶段要调用哪个 bean 操作。
但是,如果您没有任何要验证/值更改检查的输入字段,也没有任何行中的任何按钮/链接,那么我可以想象应用请求值阶段期间的查询在您看来完全是多余的。
不幸的是,您无法完全禁用它。从技术上讲,唯一的方法是将数据 bean 放入会话范围中,并仅在 bean 的构造函数和 bean 操作方法中执行昂贵的 SQL 查询(以及数据模型的刷新),以便仅在 bean 运行期间调用它。构造(对于第一个视图)和 bean 的操作方法期间(在新的排序/过滤器/任何请求期间)。然而,缺点是数据模型中的任何更改都会反映在最终用户在同一会话中打开的所有窗口/选项卡中,这可能会导致“wtf?”最终用户的体验。
现在,Tomahawk 是第一个针对
的preserveDataModel
属性提供了一个很好的解决方法的解决方案,它基本上将数据模型放入请求中-特定的组件树(它又已经存储在会话范围中或客户端的隐藏输入字段中,具体取决于您在 faces-config 中配置视图状态的存储位置的方式)。 RichFaces 没有类似的直接解决方案,但
的作用基本相同。它只会影响“整个”bean,因此如果您的数据 bean 不仅仅包含数据模型,您可能会考虑重构它。您应该记住将 bean 设计为会话范围的 bean。如果数据模型变得很大,那么我可以想象这会影响服务器内存,但是如果您只将数据模型的可查看部分存储在内存中(因此不是整个数据模型,包括所有其他页面)。看看它是否超过在单个 HTTP 请求期间触发两次 SQL 查询的成本。
希望这有帮助。
The getter call during apply request values phase is mandatory because JSF needs to know which input values were initially shown so that it can eventually do any validation and/or call any valuechangelisteners in the next phase where applicable. It is also mandatory to find out which button/link was pressed/clicked in any of the rows so that it knows which bean action to call in the invoke action phase.
But if you don't have any input fields which are to be validated/valuechange-checked nor any buttons/links in any of the rows, then I can imagine that the query during apply request values phase is in your eye completely superfluous.
Unfortunately, you can't completely disable it. Technically, the only resort to that is putting the data bean in the session scope and do the expensive SQL query (and refresh of datamodel) only in the constructor of the bean and in the bean action method, so that it only get invoked during bean's construction (for 1st view) and during bean's action method (during a new sort/filter/whatever request). The disadvantage is however that any changes in the datamodel are reflected in all windows/tabs the enduser has open in the same session, which might cause "wtf?" experiences for the enduser.
Now, Tomahawk was the first which has a nice workaround for this in flavor of the
preserveDataModel
attribute for the<t:dataTable>
, which basically puts the datamodel in the request-specific component tree (which in turn is already stored in the session scope or in a hidden input field in the client side, depending on how you configured the store location of the view state in faces-config). RichFaces doesn't have a direct solution like that, but the<a4j:keepAlive>
does basically the same. It would only affect the "whole" bean, thus if your data bean contains more than only the datamodel, you might consider to refactor it. You should keep in mind to design the bean as if it is a session scoped bean.If the datamodel gets large, then I can imagine that this impacts the server memory, but this shouldn't really harm that much if you only stores the viewable part of the datamodel in memory (and thus not the entire datamodel, including all the other pages). See if it outweighs the cost of firing double SQL queries during a single HTTP request.
Hope this helps.