如何在抽象 JPA 条件查询中使用 JSF ListDataModel 对象
How to use JSF ListDataModel object in abstract JPA criteria query
我正在使用 JPA 2 EclipseLink 开发 JSF 应用程序。我需要使用我的列表的 ListDataModel 实现而不是普通的 List 实现。我想把这个方法放在一个抽象外观 class 中,这样它就可以在整个应用程序中使用。对于普通的 List 实现,抽象 class
public List<T> findAll() {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
return getEntityManager().createQuery(cq).getResultList();
}
抽象class实现是:
@Stateless
public class ExportFacade extends AbstractFacade<Export> {
@PersistenceContext(unitName = "GazpromModulePU")
private EntityManager em;
@Override
protected EntityManager getEntityManager() {
return em;
}
public ExportFacade() {
super(Export.class);
}
上述方法的结果正确显示,一切正常。现在我想做完全相同的事情,但 return ListDataModel 中的结果。我试过了:
public ListDataModel<T> findAllListDataModel() {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
return new ListDataModel<T>(getEntityManager().createQuery(cq).getResultList());
}
使用相同的实现(和上面的抽象方法),列表不显示,错误控制台是 blank.I 可以使用如下方法手动硬编码 ListDataModel:
public ListDataModel<Export> hardCodedMethod() {
if(someList == null) {
someList = makeModel();
}
return someList;
}
public ListDataModel<Export> makeModel() {
List<Export> elist = myFacade.findAll();
ListDataModel<Export> model = new ListDataMOdel<Export>(eList);
return model;
}
我想抽象地实现上述代码 class 而不是在整个应用程序中对其进行硬编码。非常感谢任何指导。提前致谢!
首先,您不应该在服务中包含任何 JSF 工件 class。这将您的业务层与当前的 Web 层紧密耦合。换句话说,您的业务层不可跨不同的 Web 层重用,例如 RESTful、Websockets、普通 JSP/Servlet 等
不要更改您的服务 class。继续从中返回 List
。确保在任何服务 class 中没有任何 import javax.faces.***
行。改为在 JSF 端解决您的问题。例如。创建一个抽象支持 bean。
public abstract class ListDataModelBacking<T> {
private transient ListDataModel<T> model;
public abstract List<T> getListFromService();
public ListDataModel<T> getModel() {
if (model == null) {
model = new ListDataModel<>(getListFromService());
}
return model;
}
}
请注意,DataModel
实现应该是不可序列化的。
然后你可以在常规的支持 bean 中使用它,如下所示:
@Named
@ViewScoped
public class FooBacking extends ListDataModelBacking<Foo> implements Serializable {
@Inject
private FooService fooService;
@Override
public List<Foo> getListFromService() {
return fooService.listAll();
}
}
<h:dataTable value="#{fooBacking.model}" ...>
或者,打 ListDataModel
并寻找一个更简单的解决方案来解决您试图通过在 bean 中使用 ListDataModel
属性 来解决的具体功能需求。也许 EL 2.2 能够传递方法参数?另见 a.o。 How can I pass selected row to commandLink inside dataTable?
我正在使用 JPA 2 EclipseLink 开发 JSF 应用程序。我需要使用我的列表的 ListDataModel 实现而不是普通的 List 实现。我想把这个方法放在一个抽象外观 class 中,这样它就可以在整个应用程序中使用。对于普通的 List 实现,抽象 class
public List<T> findAll() {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
return getEntityManager().createQuery(cq).getResultList();
}
抽象class实现是:
@Stateless
public class ExportFacade extends AbstractFacade<Export> {
@PersistenceContext(unitName = "GazpromModulePU")
private EntityManager em;
@Override
protected EntityManager getEntityManager() {
return em;
}
public ExportFacade() {
super(Export.class);
}
上述方法的结果正确显示,一切正常。现在我想做完全相同的事情,但 return ListDataModel 中的结果。我试过了:
public ListDataModel<T> findAllListDataModel() {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
return new ListDataModel<T>(getEntityManager().createQuery(cq).getResultList());
}
使用相同的实现(和上面的抽象方法),列表不显示,错误控制台是 blank.I 可以使用如下方法手动硬编码 ListDataModel:
public ListDataModel<Export> hardCodedMethod() {
if(someList == null) {
someList = makeModel();
}
return someList;
}
public ListDataModel<Export> makeModel() {
List<Export> elist = myFacade.findAll();
ListDataModel<Export> model = new ListDataMOdel<Export>(eList);
return model;
}
我想抽象地实现上述代码 class 而不是在整个应用程序中对其进行硬编码。非常感谢任何指导。提前致谢!
首先,您不应该在服务中包含任何 JSF 工件 class。这将您的业务层与当前的 Web 层紧密耦合。换句话说,您的业务层不可跨不同的 Web 层重用,例如 RESTful、Websockets、普通 JSP/Servlet 等
不要更改您的服务 class。继续从中返回 List
。确保在任何服务 class 中没有任何 import javax.faces.***
行。改为在 JSF 端解决您的问题。例如。创建一个抽象支持 bean。
public abstract class ListDataModelBacking<T> {
private transient ListDataModel<T> model;
public abstract List<T> getListFromService();
public ListDataModel<T> getModel() {
if (model == null) {
model = new ListDataModel<>(getListFromService());
}
return model;
}
}
请注意,DataModel
实现应该是不可序列化的。
然后你可以在常规的支持 bean 中使用它,如下所示:
@Named
@ViewScoped
public class FooBacking extends ListDataModelBacking<Foo> implements Serializable {
@Inject
private FooService fooService;
@Override
public List<Foo> getListFromService() {
return fooService.listAll();
}
}
<h:dataTable value="#{fooBacking.model}" ...>
或者,打 ListDataModel
并寻找一个更简单的解决方案来解决您试图通过在 bean 中使用 ListDataModel
属性 来解决的具体功能需求。也许 EL 2.2 能够传递方法参数?另见 a.o。 How can I pass selected row to commandLink inside dataTable?