有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

javajpa标准查询。如何摆脱字符串参数。在条件api中生成不带字符串的查询。类型安全查询

我正在尝试从JPA JPQL查询转移到我的应用程序中的条件查询

主要原因是我已经厌倦了重构字符串和修复大量运行时jpa异常,这些异常是由非类型安全JPQL的引起的

我在网上搜索了其他支持类型安全和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或编译时出错。我将不得不在运行时测试它,这在像我这样的大型项目上是不好的

我使用:

  • 带hibernate的JPA
  • jdbc
  • 游戏框架

请帮忙


共 (1) 个答案

  1. # 1 楼答案

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

    示例实体:

    @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