首先,抱歉我的英语。我有一个RequestScoped ManagedBean,以便将参数发送到其他视图,而不会得到The scope of the object referenced by expression is shorter than the referring managed beans
错误。我在同一个RequestScoped视图中也有一个显示这些bean对象的p:dataTable
,每行都有一个更新按钮,它将该bean检索到同一视图中的另一个表单,以便用新值进行更新。
问题是,当我点击提交按钮来记录新值时,会创建另一条记录,而不是更新的旧记录。当然,因为按下提交按钮(RequestScoped)时bean被杀死,所以在DB中创建一个新bean和另一条记录。如何在此范围内修复它?
我已经看到了使用@PostConstruct here的一些替代方案,但是我不完全确定它会解决我的具体问题。
编辑:
在对this topic进行了更多的研究之后,我又出现了另一个疑问:我在两个视图中都使用相同的Bean(在我的例子中是ProjectBean),我应该创建一个带有RequestScoped注释的新Bean(类似于ProjectIdBean),设置较旧的Bean到ViewScoped(所以我可以自然地在我的数据库上重现更新),并让这个新的Bean处理其他视图的请求?
提交按钮:<p:commandButton value="Gravar" action="#{projetoBean.gravar}"
process="@form" update="@form :formTabelaProjetos:tabelaProjetos" />
'保存'方法:
public void gravar() {
System.out.println("Gravando projeto " + this.projeto.getNome());
ProjetoDAO dao = new ProjetoDAO();
if (this.projeto.getId() == null) {
dao.adiciona(this.projeto);
projetosAtivos = this.getProjetosAtivos();
} else {
dao.atualiza(this.projeto);
}
this.projeto = new Projeto();
}
您可以使用请求范围的辅助bean来更新实体。问题是,请求生命周期在呈现页面时结束。所以你装的任何东西都会被丢弃。提交创建另一个请求,它将尝试重新加载资源,但它与前一个请求不同,例如请求参数通常不包含程序员期望的内容。但这就是你已经发现的。如何处理问题有两种方法:
1)使用简单的getter和setter在请求范围bean中设置“String,Integer”和类似变量,用于重建和修改要更新的实体。程序员不方便,但请求范围bean可以节省服务器的资源。
2)改变你的支持bean的范围。会话范围并不理想,因为它可以在内存中保留很长时间。您可能会意识到需要手动清理它。更好的是ViewScoped bean,因为它允许您使用通过几个步骤加载的实体。当用户离开页面时,它会被清除。
@javax.faces.bean.ViewScoped
@javax.faces.bean.ManagedBean
public class SomethingBean {
......
}