JPA标准查询。如何摆脱字符串参数。在条件api中构建没有字符串的查询。输入安全查询

时间:2015-07-03 09:34:55

标签: java eclipse jpa types criteria-api

我正试图在我的应用程序中从JPA JPQL查询转向Criteria Query。

主要原因是我厌倦了重构字符串并修复了由 Not typesafe JPQL&#39> 引起的大量运行时jpa异常。

我在网上搜索其他支持typeafe和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();
}

正如您所看到的那样,有字符串:

  • &#34;平衡&#34;
  • &#34; OWNERNAME&#34;

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

我用:

  • JPA with hibernate
  • JDBC
  • playFramework

请帮忙。

1 个答案:

答案 0 :(得分:2)

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

示例实体:

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

生成元模型(在编写/编写Order类时由eclipse IDE自动完成。原始类中的每个更改: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