【问题标题】:Parameter in like clause JPQL类似子句 JPQL 中的参数
【发布时间】:2010-11-23 09:20:38
【问题描述】:

我正在尝试使用 like 子句编写 JPQL 查询:

LIKE '%:code%'

我想要 code=4 并找到

455 554 646 ...

我不能通过:code = '%value%'

namedQuery.setParameter("%" + this.value + "%");

因为在另一个地方我需要:value,而不是被% 字符包裹。有什么帮助吗?

【问题讨论】:

  • @Manuele Piastra:下面的答案不是您想要的吗?

标签: java jpa eclipselink jpql sql-like


【解决方案1】:

如果你这样做了

LIKE :code

然后做

namedQuery.setParameter("code", "%" + this.value + "%");

然后 value 仍然没有 '%' 符号。如果您需要在同一查询中的其他地方使用它,只需使用 'code' 以外的其他参数名称。

【讨论】:

  • 郑重声明,这不会让您受到 JPQL 注入攻击,因为 this.value 会自动为您正确转义。
  • 这个"%" + this.value + "%" 是被转义的。
  • 如何使这个不区分大小写?
【解决方案2】:

我不会对所有查询使用命名参数。例如,在JpaRepository 中使用命名参数是不常见的。

解决方法我使用 JPQL CONCAT 函数(此代码模拟 开头):

@Repository
public interface BranchRepository extends JpaRepository<Branch, String> {
    private static final String QUERY = "select b from Branch b"
       + " left join b.filial f"
       + " where f.id = ?1 and b.id like CONCAT(?2, '%')";
    @Query(QUERY)
    List<Branch> findByFilialAndBranchLike(String filialId, String branchCode);
}

我在优秀的文档中发现了这种技术:http://openjpa.apache.org/builds/1.0.1/apache-openjpa-1.0.1/docs/manual/jpa_overview_query.html

【讨论】:

  • 注意:CONCAT(?2, '%') 将在参数末尾添加 '%',使用 CONCAT('%', ?2, '%') 将其添加到参数的开头和结尾。
  • 添加到上面的注释中,在 Oracle 中的语法是:CONCAT(CONCAT('%', ?2), '%') 将 % 添加到字符串的开头和结尾。
【解决方案3】:

您可以使用JPA LOCATE function

LOCATE(searchString, CandidateString [, startIndex]):返回 候选字符串中 searchString 的第一个索引。位置是从 1 开始的。 如果未找到该字符串,则返回 0。

仅供参考:my top google hit 上的文档将参数颠倒了。

SELECT 
  e
FROM 
  entity e
WHERE
  (0 < LOCATE(:searchStr, e.property))

【讨论】:

  • 对我来说最好的解决方案 - 没有连接,没有 SQL 注入。
【解决方案4】:

我不知道我是迟到还是超出范围,但我认为我可以这样做:

String orgName = "anyParamValue";

Query q = em.createQuery("Select O from Organization O where O.orgName LIKE '%:orgName%'");

q.setParameter("orgName", orgName);

【讨论】:

    【解决方案5】:

    JPA 标准 API 中有一个不错的 like() 方法。尝试使用它,希望它会有所帮助。

    CriteriaBuilder cb = em.getCriteriaBuilder();
    CriteriaQuery criteriaQuery = cb.createQuery(Employees.class);
    Root<Employees> rootOfQuery = criteriaQuery.from(Employees.class);
    criteriaQuery.select(rootOfQuery).where(cb.like(rootOfQuery.get("firstName"), "H%"));
    

    【讨论】:

      【解决方案6】:

      使用JpaRepositoryCrudRepository 作为存储库接口:

      @Repository
      public interface CustomerRepository extends JpaRepository<Customer, Integer> {
      
          @Query("SELECT t from Customer t where LOWER(t.name) LIKE %:name%")
          public List<Customer> findByName(@Param("name") String name);
      
      }
      
      
      @Service(value="customerService")
      public class CustomerServiceImpl implements CustomerService {
      
          private CustomerRepository customerRepository;
          
          //...
      
          @Override
          public List<Customer> pattern(String text) throws Exception {
              return customerRepository.findByName(text.toLowerCase());
          }
      }
      

      【讨论】:

        【解决方案7】:
        1. 使用下面的 JPQL 查询。
        select i from Instructor i where i.address LIKE CONCAT('%',:address ,'%')");
        
        1. 使用以下标准代码:
        @Test
        public void findAllHavingAddressLike() {
            CriteriaBuilder cb = criteriaUtils.criteriaBuilder();
            CriteriaQuery<Instructor> cq = cb.createQuery(Instructor.class);
            Root<Instructor> root = cq.from(Instructor.class);
            printResultList(cq.select(root).where(
                cb.like(root.get(Instructor_.address), "%#1074%")));
        }
        

        【讨论】:

          【解决方案8】:

          省略''

          LIKE %:code%
          

          【讨论】:

          • 投反对票:不起作用,这会将参数名称更改为代码%
          • 这个答案非常错误和误导,你不能在 JPA 查询中这样做
          • Spring Data 似乎接受这种语法(在 @Query 注释中),而 JPQL 不接受。
          猜你喜欢
          • 2011-04-06
          • 2016-03-30
          • 2012-09-05
          • 2014-10-30
          • 2015-07-05
          • 2015-10-23
          • 2012-02-04
          相关资源
          最近更新 更多