向本地 Spring JPA @Query 传递整个 where 子句

4

目前我无法确定在创建Spring @Query中的本地SQL时,将包含哪些字段(例如adhoc)。因此,我正在传递整个where子句。

如果我将SQL输出到控制台并将其粘贴到我的SQL编辑器中,我就能够获得有效的结果集。

SELECT * FROM lorder WHERE order_id = 1196077

上一次打印到控制台的SQL输出为: Hibernate:
/* dynamic native SQL query */ SELECT
    * 
FROM
    lorder 
WHERE
    ?
and the where clause value being passed in to the @query is:
order_id = 1196077

目前我在做的事情没有起到作用。

@Query(
    value = "SELECT * FROM lorder WHERE :where",
    nativeQuery = true)
List<OrderEntity> listSelected(@Param("where") String where);  

我不确定是否可以传递整个where子句,但我期望得到一个列表。然而,目前我的结果是一个空集合。


1
我无法理解你想要实现什么,以及为什么要使用本地查询而不是JPQL查询。如果你想执行一个动态创建的查询,则应该使用Criteria API或QueryDSL。这就是它们的用途。如果你想使用单个方法来执行多个不同的静态查询,那就不要这样做:这会使测试该方法变得不可能,无法多次重用它,使代码变得不够清晰,测试变得更加脆弱。 - JB Nizet
谢谢JB。我已经更改为使用Query query = entityManager.createQuery("Select...)。 - shadley
请查看Spring Data JPA中的JpaSpecificationExecutor<T>Specification<T> - t4dohx
2个回答

6

由于在使用@Query的注释时,你只能使用命名参数(例如:where)或序数参数(例如?1?2)的特定Java类型,因此无法注入部分SQL表达式。

但是,您可以使用TypedQuery将部分SQL添加到查询中:

  public List<OrderEntity> getOrdersUsingWhereClause(EntityManager em, String whereClause) {
    TypedQuery<OrderEntity> query = em.createQuery(
        "SELECT o FROM lorders o WHERE " + whereClause,
        OrderEntity.class);
    return query.getResultList();
  }

请参阅https://www.objectdb.com/java/jpa/query/parameter#Parameters_vs.Literals


1
我认为需求本身以及答案都容易受到 SQL 注入攻击的威胁,除非你在外层处理这种攻击。 - Jayr
@Jayr 完全同意。这是 OP 必须意识到的权衡:__安全性__(受潜在 SQL 注入威胁)与 __灵活性__(通过简单注入用户定义的 SQL 部分获得)。请继续评论原帖,询问是否有其他值得考虑的要求。 - hc_dev
我的版本将实体作为字符串传递,并使用反射获取实体类。然而,存在一个限制。带有嵌入分号的whereClause将失败。例如,whereClause =“description like'%;%'”。 - Rick

0

1
使用“Criteria Queries”是一种可行的方法,它具有安全性好处(禁止SQL注入),但在运行时限制了灵活性,只允许在设计时编码WHERE条件。很棒,你提供了这些链接来学习。继续添加一些代码尝试解决具体问题 :-) - hc_dev

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接