如何以编程方式验证 JPQL(JPA 查询)

Posted

技术标签:

【中文标题】如何以编程方式验证 JPQL(JPA 查询)【英文标题】:How to validate JPQL (JPA query) programmatically 【发布时间】:2015-09-18 19:54:51 【问题描述】:

我正在寻找一种以编程方式验证 JPA 查询的方法。

在(Spring)事务中,我有一个要运行的查询列表。这些查询可能包含我想捕获的语法错误,以便事务可以继续。

我的第一个想法是使用EntityManager 并创建和执行我的查询,如果它们失败,那么我可以简单地捕获异常,记录警告并继续。

问题是当出现问题时,事务被标记为rollbackOnly,所以我当前的事务被回滚,这不是我想要的。

在伪代码中,它或多或少是这样的:

  EntityManager em = ...;
  em.getTransaction().begin();
  List<String> queries = Arrays.asList("select e from Department d", 
             "select d from Department d");
  for(String query:queries) 
       TypedQuery<Department> typedQuery = em.createQuery(query, Department.class); // This can throw an exception
       List<Department> deps = typedQuery.getResultList(); // This can also throw an exception
       //... do some stuff with the departements
  

到目前为止,我发现的替代方法是从原始的 (em.getEntityManagerFactory().createEntityManager()) 创建另一个 EntityManager,首先在该查询中运行我的查询,然后在原始查询中重新执行它们(如果成功),但这确实效率不高,而且看起来很丑。

我正在使用 EclipseLink 作为 JPA 实现,我无法切换到另一个 JPA 实现。

【问题讨论】:

EclipseLink 应该有一个jpql.validation 扩展,它可以使用 HermesParser 验证 JPQL 表达式。 如果你可以使用注解,那么也许像@Transactional(noRollbackFor=BadSqlGrammarException.class) @6ton 不幸的是,这是 eclipselink(可能还有 JPA)内部的东西,所以修改注释不会改变任何东西。 @meskobalazs 您是否有关于该解析器以及如何使用它的其他信息? 尝试看看 嵌套工作单元 wiki.eclipse.org/… 文档中的要点是 嵌套工作单元的失败不会影响提交或回滚父工作单元中其他操作的事务。希望这是您正在寻找的一个 【参考方案1】:

我想您想要对 JPQL 进行编译时验证。无法检查查询语法是否正确。

为了完成您想要的工作,请使用标准 api 而不是 JPQL。 检查标准 api 的文档。您需要使用元模型进行编译时检查

【讨论】:

如何将 CriteriaBuilder 与从数据库中获取的字符串一起使用? 请查看官方文档:docs.oracle.com/javaee/6/tutorial/doc/gjrij.html Criteria api 使用对象级操作。 我知道,但不能在这种情况下使用,因为查询是由数据库中的用户编写的。 如果我理解正确,您要运行的查询是从数据库中的其他用户写入的,然后您检索它们。

以上是关于如何以编程方式验证 JPQL(JPA 查询)的主要内容,如果未能解决你的问题,请参考以下文章

JPQL 的 Spring Boot JPA“查询验证失败”错误

如何在 JPQL(Spring JPA 查询)中使用 JOIN 执行 UPDATE 语句?

如何在 JPA JPQL 查询中加入两个实体集合?

JPA JPQL简介

JPA 中的传递列表命名本机查询

Hibernate:如何通过连接字符串来创建 JPQL?