java - 创建一个使用 JPA2 和 CriteriaBuilder 的通用方法

标签 java jpa-2.0

我正在开发一个使用 JSF2 和 JPA2 框架的网络应用程序。 我开始在 netbeans7.0 上使用向导,“实体类的新 JSF 页面”创建了一个 classAbstractFacade“包含这个有用的方法:

public List<T> findRange(int[] range) {
  javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
  cq.select(cq.from(entityClass));
  javax.persistence.Query q = getEntityManager().createQuery(cq);
  q.setMaxResults(range[1] - range[0]);
  q.setFirstResult(range[0]);
  return q.getResultList();
}

其中 T 是包含表的数据库结构的实体类,范围变量包含两个数字,用于检索结果的子列表! 现在我修改它以设置一个 order by 子句并检查用户是否在一个范围内,新代码是:

    public List<T> findRangeOrdered(int[] range, String orderBy) {
      javax.persistence.criteria.CriteriaQuery<T> cq = (javax.persistence.criteria.CriteriaQuery<T>)getEntityManager().getCriteriaBuilder().createQuery();
      cq.select(cq.from(entityClass));
      javax.persistence.criteria.Root<T> r = cq.from(entityClass);
      if(orderBy!=null && !orderBy.equals("")){
        if(orderBy.ebdsWith(" desc"))
          cq.orderBy(getEntityManager().getCriteriaBuilder().desc(r.get(orderBy.substring(0,orderBy.indexOf(" ")))));
        else
          cq.orderBy(getEntityManager().getCriteriaBuilder().desc(r.get(orderBy.substring(0,orderBy.indexOf(" ")))));
      }
      javax.persistence.Query q = getEntityManager().createQuery(cq);
      if(range!=null)
      {
        q.setMaxResults(range[1] - range[0]);
        q.setFirstResult(range[0]);
      }
      return q.getResultList();
    }

现在我要添加一些 where 选项。 我正在考虑添加一个 List 变量,它可以包含一个 HashMap 和这对键--> 值:

  • "type"--> 我要搜索的字段类型(例如 String.class 或 java.util.Date.class);
  • "name"--> 实体类上字段的名称;
  • "value0"--> 我要查找的第一个值;
  • "value1"--> "between"子句的第二个值;
  • "clause"--> 我想使用哪个过滤器。

现在我有一些疑问:

1) 这个想法是个好主意吗?

2) 做一个已经实现了这个功能的框架导出?

3) 如果前面问题的答案是:是的,这是个好主意;不,没有任何框架已经做到了,我发现了这些新问题: 这个新方法返回一些编译器错误:

public List<T> findAllFiltered(int[] range, String orderBy, List<HashMap<String,Object>> whereList) {
  List<Predicate> predicateList = new ArrayList<Predicate>();
  String buf;
  HashMap<String,Object> where;
  int i=0;
  javax.persistence.criteria.CriteriaQuery<T> cq = (javax.persistence.criteria.CriteriaQuery<T>)getEntityManager().getCriteriaBuilder().createQuery();
  cq.select(cq.from(entityClass));
  javax.persistence.criteria.Root<T> r = cq.from(entityClass);
  javax.persistence.criteria.Path<T> path = cq.from(entityClass);
  if(whereList!= null && whereList.size()>0){
    Iterator iter=whereList.iterator();
    Predicate p;
    while (iter.hasNext())    
    {
      where=(HashMap<String,Object>)iter.next();

      if(where.get("where").toString().equals("like"))
        p = getEntityManager().getCriteriaBuilder().like(getEntityManager().getCriteriaBuilder().upper(r.<String>get(where.get("name").toString())), "%"+where.get("value0").toString().toUpperCase()+"%");
      else if(where.get("where").toString().equals("equal"))
        p = getEntityManager().getCriteriaBuilder().equal(r.get(where.get("name").toString()), where.get("value0").toString());
      else if(where.get("where").toString().equals("in"))
        p = getEntityManager().getCriteriaBuilder().and(r.get(where.get("name").toString()).in(where.get("value0").toString().replaceAll("#",",")));
      else if(where.get("where").toString().equals("between"))
      {
        java.util.Date value0=(java.util.Date)where.get("value0");
        java.util.Date value1=(java.util.Date)where.get("value1");
        p = getEntityManager().getCriteriaBuilder().between(r.<java.util.Date>get(where.get("name").toString()),value0,value1);
      }
      else if(where.get("where").toString().equals("greatest"))
        p = getEntityManager().getCriteriaBuilder().and(getEntityManager().getCriteriaBuilder().greatest(r.<Long>get(where.get("name").toString())));
      else if(where.get("where").toString().equals("greaterThanOrEqualTo"))
      {
        java.util.Date value0=(java.util.Date)where.get("value0");
        p = getEntityManager().getCriteriaBuilder().greaterThanOrEqualTo(r.<java.util.Date>get(where.get("name").toString()),value0);
      }
      else if(where.get("where").toString().equals("lessThanOrEqualTo"))
      {
        java.util.Date value0=(java.util.Date)where.get("value0");
        p = getEntityManager().getCriteriaBuilder().lessThanOrEqualTo(r.<java.util.Date>get(where.get("name").toString()),value0);
      }

    }
  }
  Predicate[] predicates = new Predicate[predicateList.size()];
  predicateList.toArray(predicates);
  cq.where(predicates);

  if(orderBy!= null&& !orderBy.equals("")){
    if(orderBy.endsWith("desc"))
      cq.orderBy(getEntityManager().getCriteriaBuilder().desc(r.get(orderBy.substring(0,orderBy.indexOf(" ")))));
    else
      cq.orderBy(getEntityManager().getCriteriaBuilder().asc(r.get(orderBy.substring(0,orderBy.indexOf(" ")))));
  }

  javax.persistence.Query q = getEntityManager().createQuery(cq);
  if(range!=null){
    q.setMaxResults(range[1] - range[0]);
    q.setFirstResult(range[0]);
  }
  return q.getResultList();
}

1) "greatest"方法返回这个错误:

p = getEntityManager().getCriteriaBuilder().and(getEntityManager().getCriteriaBuilder().greatest(r.<Long>get(where.get("name").toString())));
method CriteriaBuilder.and(Expression<Boolean>,Expression<Boolean>) is not applicable
(actual and formal argument lists differ in length)
method CriteriaBuilder.and(Predicate...) is not applicable
(argument type Expression<Long> does not conform to vararg element type Predicate)

我搜索了此方法的示例,但没有找到任何有用的信息;

2) 如我所写,我的 HashMapp 还包含我想要过滤的字段类,现在我将使用此信息重写 between,greaterThanOrEqualTo,lessThanOrEqualTo 所以,如果我愿意,我可以过滤除 java 之外的其他类型.util.日期! 你怎么看待这个长问题? 感谢您的帮助!

P.S.:抱歉我的英语不完美,但我是意大利人。

P.S.2:抱歉,对于我的代码结构...我是盲人,我不会一直控制缩进...这个网站控制它但我不确定我是否缩进了所有代码正确!

最佳答案

恕我直言,这不是个好主意。您正在重新发明一种新的通用查询语言,这种新的查询语言将是

  • 表达能力不如 JPQL
  • 非标准
  • 类型安全性低于 Criteria API
  • 效率低于 JPQL 和 Criteria

所以你的问题的答案是

  1. 不,这不是个好主意
  2. 是的,这样的框架已经存在。它称为 JPQL。

关于java - 创建一个使用 JPA2 和 CriteriaBuilder 的通用方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8309589/

相关文章:

java - 找不到适用于 jdbc :mysql://localhost/<myDB> 的合适驱动程序

java - 我如何在 persistence.xml 中定义 <non-jta-data-source> </non-jta-data-source> ?

java - 使用 JDK 1.8,无法扩展 WToolkit 类

java - 如何同时调用onclick和a href

jpa - UserTransaction 和 EntityManager 是如何交互的?

java - 具有两个参数的 Hibernate CriteriaBuilder

java - 在 JPA Hibernate 中映射队列集合

maven-2 - JPA 2.0 API Maven 工件

java - Java中声明二进制数的 "meta"是什么?

java - Calendar.getInstance() 和 GregorianCalendar.getInstance() 之间的区别