PrimeFaces DataTable为空求助:从MySQL加载数据方案
我帮你梳理下导致PrimeFaces DataTable为空的几个关键问题,一个个来解决:
1. EL表达式大小写不匹配(最可能导致空表的原因)
JSF的EL表达式是大小写敏感的,你的代码里有两处明显的不匹配:
- 托管Bean的名称是
productM(@ManagedBean(name="productM")),但页面里用的是#{ProductM.produits}(大写P开头),应该改成#{productM.produits}。 - 实体类的属性是驼峰命名(比如
prixAchat、dateCreation),对应的EL表达式要和getter方法的属性名一致(比如getPrixAchat()对应#{produit.prixAchat}),但你页面里写的是全小写的prixachat、datecreation,这会导致无法读取属性值。
2. Lazy加载配置错误
你的DataTable设置了lazy="true",但并没有实现PrimeFaces的LazyDataModel接口,只是直接绑定了一个普通List。Lazy模式需要自定义模型来处理分页和数据加载逻辑,如果不需要懒加载,直接把lazy="true"去掉即可,这样DataTable会直接加载整个列表数据。
3. 页面XML命名空间拼写错误
页面开头的<html xlmns="http://www.w3.org/1999/xhtml"里的xlmns是拼写错误,正确的是xmlns。这个错误会导致JSF和PrimeFaces的标签无法被正确解析,进而影响DataTable的渲染。
4. 实体类缺少JPA注解(Hibernate无法映射数据库表)
你的Product类没有添加JPA的实体注解,Hibernate根本不知道它对应数据库里的products表,执行from Product查询时要么报错,要么返回空列表。必须给实体类添加注解:
package ma.supmti.jsf.model; import java.util.Date; import javax.persistence.Entity; import javax.persistence.Id; import javax.persistence.Table; @Entity @Table(name = "products") // 明确对应MySQL的products表 public class Product { @Id // 标记主键字段 private Integer id; private String name; private Integer prixAchat; private Integer prixVente; private Date dateCreation; // 构造函数、getter、setter保持不变 }
5. 托管Bean作用域不合理
你给ProductMB用了@ApplicationScoped,这个作用域是整个应用共享的,初始化一次后就不会再更新数据。对于列表页面来说,@ViewScoped更合适,它会绑定到当前页面的生命周期,每次进入页面都会重新初始化数据:
@ManagedBean(name="productM") @ViewScoped // 替换@ApplicationScoped public class ProductMB implements Serializable { // 其他代码保持不变 }
6. Hibernate资源管理问题(潜在的查询失败原因)
你的DAOProduct每次查询都创建新的SessionFactory,这不仅效率低,还可能导致资源泄漏。应该把SessionFactory做成静态单例,并且正确管理Session的事务和关闭:
package ma.supmti.jsf.dao; import org.hibernate.query.Query; import ma.supmti.jsf.model.Product; import java.util.List; import org.hibernate.Session; import org.hibernate.SessionFactory; import org.hibernate.cfg.Configuration; public class DAOProduct implements IDAOProduct { // 静态单例SessionFactory private static SessionFactory sessionFactory; static { try { Configuration config = new Configuration().configure("hibernate.cfg.xml"); sessionFactory = config.buildSessionFactory(); } catch (Throwable ex) { throw new ExceptionInInitializerError(ex); } } public DAOProduct() { } public void addProduct() { } public List<Product> selectProduct() { Session session = sessionFactory.openSession(); List<Product> produits = null; try { session.beginTransaction(); // 指定泛型类型,避免强制转换 Query<Product> query = session.createQuery("from Product", Product.class); produits = query.list(); // 控制台打印数据,确认是否查询到结果 for(Product produit:produits) { System.out.println("Produit: " + produit.getName() + ", Prix Achat: " + produit.getPrixAchat()); } session.getTransaction().commit(); } catch (Exception e) { // 异常时回滚事务 if (session.getTransaction().isActive()) { session.getTransaction().rollback(); } e.printStackTrace(); } finally { // 关闭Session,释放资源 session.close(); } return produits; } }
修改后的页面代码
把上面的问题都修正后,页面代码应该是这样的:
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml" xmlns:f="http://java.sun.com/jsf/core" xmlns:h="http://java.sun.com/jsf/html" xmlns:p="http://primefaces.org/ui" xmlns:ui="http://java.sun.com/jsf/facelets"> <h:head> <title>LISTE DES PRODUITS </title> <style type="text/css"> body { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 14px; } .header { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 18px; } .bottom { font-family: Verdana, Arial, Helvetica, sans-serif; font-size: 9px; text-align: center; vertical-align: middle; color: #8E969D; } </style> </h:head> <body bgcolor="#ffffff"> <!-- 移除lazy="true",修正EL表达式 --> <p:dataTable value="#{productM.produits}" var="produit" id="produit" paginator="true" rows="10"> <f:facet name="header"> Liste des produits ..................... </f:facet> <p:column headerText="Id"> <h:outputText value="#{produit.id}" /> </p:column> <p:column headerText="Name"> <h:outputText value="#{produit.name}" /> </p:column> <p:column headerText="Prix Achats"> <h:outputText value="#{produit.prixAchat}" /> </p:column> <p:column headerText="Prix Vente"> <h:outputText value="#{produit.prixVente}" /> </p:column> <p:column headerText="Date Creation"> <h:outputText value="#{produit.dateCreation}"> <!-- 添加日期格式化,避免默认的长日期格式 --> <f:convertDateTime pattern="yyyy-MM-dd HH:mm:ss" /> </h:outputText> </p:column> </p:dataTable> </body> </html>
最后验证步骤
- 启动应用后,查看控制台是否打印了查询到的产品数据,确认Hibernate是否正确读取了数据库内容。
- 打开页面,检查DataTable是否正常显示数据。如果还是为空,检查JSF的日志,看是否有EL表达式错误或者实体映射错误。
内容的提问来源于stack exchange,提问作者Ouafae

