我将Glassfish Server 4.1与捆绑的JSF一起使用。我已经启用了JPA FINE登录" persistence.xml"。
我有这个Facelets页面:
<p:dataTable var="customer" value="#{customerService.customers}">
</p:dataTable>
<h:form>
<h:commandButton value="Test"/>
</h:form>
(请注意,确实存在以下情况:我没有将操作与按钮相关联,或者在表格中添加了列,如果我这样做了,那我的行为就是描述并没有改变。还记得默认render
行为是@none
。)
这个无状态EJB(使用@Named
以便页面可以直接引用它):
@Stateless
@Named
public class CustomerService {
@PersistenceContext
private EntityManager em;
public List<Customer> getCustomers() {
return em.createNamedQuery("Customer.findAll", Customer.class).getResultList();
}
...
加载页面时,日志中会显示以下消息:
Fine: SELECT ID, CUSTOMERNAME, EMAIL, PAID, QUANTITY, TYPE FROM CUSTOMER
到目前为止一切顺利。当我单击按钮时,它会出现在日志中:
Fine: SELECT ID, CUSTOMERNAME, EMAIL, PAID, QUANTITY, TYPE FROM CUSTOMER
Fine: SELECT ID, CUSTOMERNAME, EMAIL, PAID, QUANTITY, TYPE FROM CUSTOMER
... Same message appears five more times ...
Customers表为空。
有人可以复制或解释这种行为吗?一个用于页面加载的SELECT是有意义的,但是表单提交的七个SELECTS令人困惑。
更新
如果我将EJB移动到ViewScoped JSF backing-bean并更新Facelets页面以使用它,行为将保持不变:
@ManagedBean // javax.faces.bean.
@ViewScoped
public class BackingBean {
@EJB
private CustomerService cs;
public List<Customer> getCustomers() {
return cs.getCustomers();
}
}
答案 0 :(得分:0)
我认为问题出在你在bean中使用的范围内,让我从其他question引用它:
如果是@Named的CDI,则默认为@Dependent,如Weld documentation中所述: 最后,CDI具有所谓的依赖伪范围。这是没有显式声明范围类型的bean的默认范围。效果是在每个单独的EL表达式上新创建了bean实例。因此,想象一个登录表单,其中两个输入字段引用bean属性,而一个命令按钮引用bean操作,因此总共有三个EL表达式,那么实际上将创建三个实例。
现在,我们如何解决它?也许你应该根据你的要求Check out this documentation about Scopes and context in JSF为你的bean尝试另一个范围。
答案 1 :(得分:0)
正如Tiny在我的问题评论中解释的那样,额外的日志记录正在发生,因为我将业务逻辑放在Facelets页面使用的getter方法中。通常不赞成将业务逻辑放在Facelets页面使用的访问器(getter 和 setter)方法中,因为这些方法由JSF框架使用,并且您几乎无法控制它们何时以及多久经常使用被称为。
在这种情况下,问题可以解决问题&#34;通过在JSF视图范围的backing-bean的@PostConstruct
方法中初始化客户:
@PostConstruct
public void init() {
customers = customerService.getCustomers();
}
public List<Customer> getCustomers() {
return customers;
}
这是一个更传统的设置,但我试图在没有JSF支持bean的情况下使用。
如果有人可以解释为什么 JSF框架正在调用方法七次,这似乎是随意的,我肯定会将答案标记为正确,但与此同时我是对此感到满意。
<强>更新强>
对确切呼叫数量的解释,七,可能与此答案相似,Why is the getter called so many times by the rendered attribute?:
在渲染响应阶段,getter调用全部由
rendered="#{selector.profilePage == 'some'}"
完成。在评估false
时 第一次,在UIComponent#encodeAll()
,然后没有更多的电话 将会完成。当它评估true
时,它将被重新评估 六 按以下顺序多次...