【问题标题】:JPA Criteria Query. How to get rid of Strings parameters. Build queries without strings in criteria api. Type safe queriesJPA 标准查询。如何摆脱字符串参数。在标准 api 中构建不带字符串的查询。键入安全查询
【发布时间】:2015-07-03 09:34:54
【问题描述】:

我正在尝试在我的应用中从 JPA JPQL 查询转移到 Criteria Query。

主要原因是我厌倦了重构字符串并修复了很多由Not typesafe JPQL's引起的运行时jpa异常。

我已经在网上搜索其他支持类型安全和 ide 重构机制的 JPA 解决方案。条件查询似乎很有希望。

标准查询中的一个想法困扰着我:

在方法参数中使用字符串。 它可以以某种方式替换为类型安全的 java 对象/变量,也许是 java 反射?

下面是示例代码:

public List<BankAccount> findWithBalance(int amount) {
    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery<BankAccount> cq = cb.createQuery(BankAccount.class);
    Root<BankAccount> from = cq.from(BankAccount.class);

    ParameterExpression<Integer> balance = cb.parameter(Integer.class);
    cq.select(from);

    Predicate predicate = cb.gt(from.<Integer> get("balance"), balance);

    cq.where(predicate);
    cq.orderBy(cb.asc(from.get("ownerName")));

    TypedQuery<BankAccount> query = em.createQuery(cq);

    query.setParameter(balance, amount);

    return query.getResultList();
}

如您所见,字符串有:

  • “余额”
  • “所有者名称”

如果我将更改此参数的名称,我将不会在 IDE 或编译时出错。我将不得不在运行时对其进行测试,这对于像我这样的大型项目来说并不好。

我用:

  • JPA 与休眠
  • jdbc
  • playFramework

请帮忙。

【问题讨论】:

  • 创建一个元模型并使用它而不是硬编码值。见docs.jboss.org/hibernate/orm/4.3/topical/html/metamodelgen/…
  • 或者使用一些框架(例如querydsl.com)。
  • 作为 CriteriaQueries 的替代方案,我会尝试使用 QueryDSL (querydsl.com)。 QueryDSL-查询更容易读写。 typeafty 也是基于生成的类。
  • @M.Deinum 感谢您的评论。你能告诉一个人想想元模型吗?是否有可能自动生成元模型类?还是我必须始终手动定义该元模型类,创建具有相同名称的 java 类,并在末尾添加下划线?

标签: java eclipse jpa types criteria-api


【解决方案1】:

元模型生成器似乎也是一个很好的解决方案:

示例实体:

@Entity
public class Order {
    @Id
    @GeneratedValue
    Integer id;
    @ManyToOne
    Customer customer;
    @OneToMany
    Set<Item> items;
    BigDecimal totalCost;
    // standard setter/getter methods
}

生成的元模型(由 eclipse IDE 在编码/编写 Order 类时自动生成。原始类中的每次更改:Order- 即使不保存文件也会在Order_ 类中自动更新):

@StaticMetamodel(Order.class)
public class Order_ {
    public static volatile SingularAttribute<Order, Integer> id;
    public static volatile SingularAttribute<Order, Customer> customer;
    public static volatile SetAttribute<Order, Item> items;
    public static volatile SingularAttribute<Order, BigDecimal> totalCost;
}

感谢我们可以构建类型安全的 sql 查询,如下所示:

CriteriaBuilder cb = entityManager.getCriteriaBuilder();
CriteriaQuery<Order> cq = cb.createQuery(Order.class);
SetJoin<Order, Item> itemNode = cq.from(Order.class).join(Order_.items);
cq.where( cb.equal(itemNode.get(Item_.id), 5 ) ).distinct(true);

Original source: JPA metamodels generator

Hibernate manual

【讨论】:

  • 不鼓励“仅链接”回复,因为只要 URL 损坏(服务器关闭、内容移走等),它们就会被破坏。问题应该在您的文本中回答;之后,您可以添加您认为有助于提供深入解释的链接。
猜你喜欢
  • 1970-01-01
  • 2020-06-21
  • 1970-01-01
  • 2019-07-22
  • 2015-11-06
  • 1970-01-01
  • 2016-06-25
  • 2012-01-17
  • 2015-07-11
相关资源
最近更新 更多