NetBeans 8.2生成实体类与JSF页面后,操作链接无法选中对应条目
我刚帮好几个新手解决过这个NetBeans生成JSF代码的坑!你的问题核心就是DataModel没有正确维护行状态,加上可能的Controller作用域配置不对,导致每次点击操作都拿不到正确的行数据,只能默认取索引0的条目,而且current变量会因为getRowData()失败变成null。
下面是一步步的排查和修复方案:
1. 检查Controller的作用域(最常见原因)
NetBeans有时候默认生成的Controller会用@RequestScoped,但JSF的DataTable行状态需要ViewScoped来保持页面请求间的状态。如果是RequestScoped,每次点击commandLink都会重新创建Controller实例,之前的DataModel状态完全丢失,rowIndex自然重置为0。
修改Controller的注解:
import javax.faces.view.ViewScoped; import javax.inject.Named; @Named @ViewScoped // 替换原来的@RequestScoped public class PictureController implements Serializable { // ... 其他代码不变 }
2. 确认DataTable和Controller的DataModel绑定正确
检查你的List.xhtml里的h:dataTable标签,value属性必须绑定到Controller里的DataModel类型的属性,而不是普通的List<Picture>。NetBeans生成的代码里,Controller应该有一个DataModel<Picture>类型的items属性,比如:
Controller里的代码:
private DataModel<Picture> items = null; public DataModel<Picture> getItems() { if (items == null) { items = new ListDataModel<>(pictureFacade.findAll()); } return items; }
页面里的DataTable要对应:
<h:dataTable value="#{pictureController.items}" var="item" ...> <!-- 列定义 --> <h:column> <h:commandLink action="#{pictureController.prepareView}" value="#{bundle.ListPictureViewLink}"/> </h:column> </h:dataTable>
如果你的getItems()返回的是List<Picture>而不是DataModel,那getRowData()根本无法获取当前行,因为普通List没有行状态管理功能。
3. 给commandLink添加显式的行数据传递(兜底方案)
如果上面的调整还是有问题,可以直接在commandLink里用f:setPropertyActionListener把当前行的对象直接传给Controller的current变量,绕过DataModel的依赖:
修改List.xhtml里的commandLink:
<h:commandLink action="#{pictureController.prepareView}" value="#{bundle.ListPictureViewLink}"> <f:setPropertyActionListener target="#{pictureController.current}" value="#{item}"/> </h:commandLink>
然后修改Controller的prepareView()方法,不需要再通过getRowData()获取:
public String prepareView() { // 现在current已经被f:setPropertyActionListener赋值了,不需要再从DataModel拿 selectedItemIndex = getItems().getRowIndex(); // 如果需要索引的话,还是可以拿 return "View"; }
4. 检查分页组件的绑定(如果用了分页)
如果你的页面有分页,还要确认pagination对象的状态也在ViewScoped里保存,否则分页后的行索引也会出错。确保pagination是Controller的成员变量,并且在ViewScoped下被正确初始化。
为什么会出现这个问题?
NetBeans的代码生成工具有时候会简化一些配置(比如默认用RequestScoped),而JSF的DataModel依赖页面级的状态保持(ViewScoped)来跟踪当前行。新手很容易忽略作用域的重要性,导致状态丢失,出现点击任何条目都跳第一条的奇怪现象。
内容的提问来源于stack exchange,提问作者Pierre

