因此,我正在尝试编写一些自定义JPQL查询生成器。 我有一个类似的端点:
/api/library/authors/search?query=test tested
在服务层上,此query
参数将像下面的JPQL查询一样转换为smth:
SELECT t FROM Author t WHERE t.fullName LIKE '%test tested%'
OR t.firstName LIKE '%test%'
OR t.firstName LIKE '%tested%'
OR t.secondName LIKE '%test%'
OR t.secondName LIKE '%tested%'
这对我来说很好用,但是firstName
或secondName
表列可能包含带有引号'
的值,例如O'Hara
。那就行不通了。
/api/library/authors/search?query=Tes O'Ha
因此,我尝试将'
替换为查询中的双引号"
,如下所示:
SELECT t FROM Author t WHERE t.fullName LIKE "%Tes O'Ha%"
OR t.firstName LIKE "%Tes%"
OR t.firstName LIKE "%O'Ha%"
OR t.secondName LIKE "%Tes%"
OR t.secondName LIKE "%O'Ha%"
我有一个例外:
org.hibernate.QueryException: unexpected char: '"'
我还尝试替换了'
上的\'
和"
上的\"
。所有这些都不起作用,并抛出一个异常...
我正在使用EntityManager执行此查询:
@Repository
public class SearchFor {
@PersistenceContext
private EntityManager entityManager;
public List execute(String query) {
return entityManager.createQuery(query).getResultList();
}
}
如何搜索包含单引号'
的值?
答案 0 :(得分:1)
我建议您在创建查询时使用索引或命名参数。这样可以解决您的问题,因为它将自动转义任何命令字符。
类似这样的东西:
em.createQuery("SELECT t FROM TestEntity t WHERE t.fullName LIKE :fullName "
+ "OR t.firstName LIKE :firstName "
+ "OR t.firstName LIKE :lastName "
+ "OR t.lastName LIKE :firstName "
+ "OR t.lastName LIKE :lastName")
.setParameter("firstName", firstName)
.setParameter("lastName", lastName)
.setParameter("fullName", fullName)
.getResultList();
我假设您是从服务层的方法参数中获取名字,姓氏,全名的。
此外,由于用户可以通过REST端点注入恶意代码,因此当前的实现还使您的应用容易受到SQL / JPQL攻击。
有关SQL注入的更多信息: https://www.baeldung.com/sql-injection
使用命名和索引参数创建查询: https://www.baeldung.com/jpa-query-parameters
答案 1 :(得分:1)
我找到了解决方案!
而且...这很简单。仅需将引号(''
JPQL查询如下所示:
SELECT t FROM Author t WHERE t.fullName LIKE '%Tes O''Ha%'
OR t.firstName LIKE '%Tes%'
OR t.firstName LIKE '%O''Ha%'
OR t.secondName LIKE '%Tes%'
OR t.secondName LIKE '%O''Ha%'
就是这样!