我正在使用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
我想通过参数动态使用表名。可能吗?如果是,请告诉我如何?
答案 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。