有没有办法在Hibernate的@query注释中使用@params中的表名?

时间:2019-07-12 05:34:02

标签: java spring hibernate jpa spring-data-jpa

我正在使用Hibernate和Spring数据JPA构建一个Web项目。

在Eclipse-Link中,我们可以使用本机查询

String tableName = "sometablename";
String query = "SELECT * FROM " +tableName +"WHERE id > 10";

在Hibernate中,我正在使用@Query注释

    @Query(value = "SELECT COUNT(r.id) as resultsCount FROM #{#resultTable} r WHERE r.customerId= :customerId AND r.is_deleted=0 AND r.is_ignored=0 ", nativeQuery = true)
Integer getResultsCount(@Param("customerId") int customerId,
            @Param("resultTable") String resultTable);

我尝试了#{#resultTable},但是这已被替换为带引号的字符串,并且出现了

You have a error in your SQL Syntax

我想通过参数动态使用表名。可能吗?如果是,请告诉我如何?

3 个答案:

答案 0 :(得分:1)

这是不可能的,@org.springframework.data.jpa.repository.Query仅采用jpql,您不能传递表名,因为它不能被识别为任何实体。

它声明Query的javadoc:

/**
 * Defines the JPA query to be executed when the annotated method is called.
 */
String value() default "";

最好的解决方案不是将表名作为字符串传递,而是使用例如继承(link)来解决它或以某种方式重建数据模型。作为一种快速而肮脏的解决方案,我建议创建一个自定义存储库并使用EntityManager.createNativeQuery并在其中传递sql。但是请记住要验证正在编写的查询(验证用户输入,使用表名枚举),因为它可能导致sql注入。

答案 1 :(得分:0)

您自己的观察结果实际上回答了您的问题:

  

我尝试了#{#resultTable},但这已被替换为带引号的字符串,并且出现了异常

@Query查询字符串中使用的占位符旨在填充 literal 值。因此,表名最终以单引号内的文字字符串形式出现。这意味着@Query和Spring可能在后台使用了JDBC准备的语句。不能 绑定表名。允许这样做将是一个重大的安全漏洞。

这里唯一可行的解​​决方法是将查询字符串连接在一起,然后尝试将该字符串与@Query一起使用。但是请注意,这不是一个安全的选择。

答案 2 :(得分:0)

您正在做的事情是错误的,您正在将业务逻辑混合到DAO层中,我建议您创建两个DAO,每个DAO都有自己的表和查询,然后在业务/服务层中调用所需的DAO。