如何在抽象JPA条件查询

时间:2015-07-19 16:57:24

标签: jsf java-ee jpa jsf-2

我正在使用JPA 2 EclipseLink开发JSF应用程序。我需要使用我的列表的ListDataModel实现而不是正常的List实现。我想将此方法放在一个抽象的Facade类中,以便它可以通过整个应用程序使用。对于普通的List实现,抽象类

public List<T> findAll() {
    javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
    cq.select(cq.from(entityClass));
    return getEntityManager().createQuery(cq).getResultList();
}

抽象类实现是:

@Stateless
public class ExportFacade extends AbstractFacade<Export> {

    @PersistenceContext(unitName = "GazpromModulePU")
    private EntityManager em;

    @Override
    protected EntityManager getEntityManager() {
        return em;
    }

    public ExportFacade() {
        super(Export.class);
    }

上述方法的结果正确显示,一切正常。现在我想做同样的事情但是在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());
}

使用相同的实现(和上面的抽象方法),不显示列表,错误控制台是空白的。我可以使用如下方法手动硬编码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;
}

我想在抽象类中实现上面的代码,而不是在整个应用程序中对其进行硬编码。非常感谢任何指导。提前谢谢!

1 个答案:

答案 0 :(得分:1)

首先,您不应该在服务类中拥有任何JSF工件。这会将您的业务层紧密耦合到当前的Web层。换句话说,您的业务层不能在不同的Web层之间重用,例如RESTful,Websockets,普通的JSP / Servlet等。

不要更改您的服务等级。继续从List返回。确保您在任何服务类中都没有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?