【问题标题】:Best way to create JPA query that might contain a parameter or might not创建可能包含参数或可能不包含参数的 JPA 查询的最佳方法
【发布时间】:2015-03-05 17:38:04
【问题描述】:

有一种方法可以像这样创建 JPA 查询

        String queryString = "SELECT i FROM Item i";

        if (null != search) {
            queryString += " WHERE i.name LIKE :pattern";
        }

        TypedQuery<Item> query = entityManager.createQuery(queryString, Item.class);

        if (null != search) {
            query.setParameter("pattern", "%" + search + "%");
        }

如果查询需要有可选的搜索字段(if null != search),有 2 个检查 避免重复的最常见方法是什么? 使用单个参数可能有 2 个命名查询,或者 Criteria API 可能允许避免这种情况(因为没有查询字符串),但是还有其他方法吗?

【问题讨论】:

  • 使用 QueryDSL!这是解决这种“代码气味”和许多其他问题的解决方案。看:querydsl.com
  • 这是一个新的lib,以前没听说过,一定会看的。

标签: java hibernate jpa


【解决方案1】:

如果您不必以编写查询字符串的方式编写查询,则可以使用 JPA Criteria API。您可以看到我称之为“ExampleDao”的类,我用于研究和示例here

然后你可以添加一个可选的 where 子句,见下面的例子:

CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Item> criteria = cb.createQuery(Item.class);
Root<Item> root = criteria.from(Item.class);
criteria.select(root);

if (null != search) {
    String pattern = "%pattern here%";
    criteria.where(cb.like(root.get("name"), pattern));
}

【讨论】:

  • 我认为你需要有类似 "root.get("name")" 的东西来编译,但这是一个非常优雅的例子。
  • 我不太喜欢 crteria api,因为元模型而且更难阅读,但看起来没有其他人会提出完全不同的建议。
  • 这肯定会编译。您可以只在实体中使用静态字符串,然后,您可以使用值为“name”的 Item.FI_NAME,而不是使用 root.get("name")。因此,您只需在实体中更改它,如果有的话,您也永远不会打错字。
  • 当我尝试编译原始帖子时,它抱怨无法将路径转换为表达式(但由于它只是类型转换,可能是我的默认设置不允许这样做)。拥有额外的静态字段看起来有点可选,但从长远来看,它可能会节省时间,而且比拥有整个元模型要好得多。
  • 在工作中,我们最初一直使用 Hibernate SessionFactory 和 Critera。您还需要告诉 Hibernate Criteria 哪些字段要使用某些限制,并且我们一直使用额外的静态字段,而不是生成元模型文件。就个人而言,我发现金属模型是一个很棒的概念,但维护起来也非常烦人。所以这就是为什么当我第一次开始我自己的项目时,我在实体类中使用我在工作中学到的方式使用静态字符串。这可能不是正确的方法,但它可以解决问题。
猜你喜欢
  • 1970-01-01
  • 2016-10-12
  • 1970-01-01
  • 2014-09-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-09-06
相关资源
最近更新 更多