JPA自定义JPQL查询中LOWER函数类型不匹配问题求助
问题:JPQL使用LOWER函数时出现类型不匹配错误
我在JPA Repository类中用JPQL编写了自定义查询,需求是当documentText列包含指定:text参数时,返回DocumentDTO类型的列表,因此对字段和参数都做了小写转换操作。
原代码如下:
@Query("SELECT new com.hakstudio.archiveapp.dto.DocumentDTO" + "(id, name, accessAuth, uploadedDate, uploadedBy, uploadedByTc, editedBy, editedByTc) " + "FROM Document " + "WHERE LOWER(documentText) LIKE CONCAT('%', LOWER(:text), '%')") List<DocumentDTO> findByDocument(@Param("text") String text);
执行时出现错误:
org.hibernate.QueryException: Parameter 1 of function lower() has type STRING, but argument is of type java.lang.String
我尝试给字段和参数添加as string转换,但没有效果:
@Query("SELECT new com.hakstudio.archiveapp.dto.DocumentDTO" + "(id, name, accessAuth, uploadedDate, uploadedBy, uploadedByTc, editedBy, editedByTc) " + "FROM Document " + "WHERE LOWER(documentText as string) LIKE CONCAT('%'," + "LOWER(:text as string)" + ",'%')") List<DocumentDTO> findByDocument(@Param("text") String text);
解决方案
这个错误是Hibernate在处理JPQL参数类型映射时的小问题,无需手动转换java.lang.String到JPQL的STRING类型,以下几种方法可以解决:
方法1:在Java层提前处理参数小写
在调用查询前将参数转换为小写,JPQL中只处理数据库字段的小写:
// Repository层代码 @Query("SELECT new com.hakstudio.archiveapp.dto.DocumentDTO(id, name, accessAuth, uploadedDate, uploadedBy, uploadedByTc, editedBy, editedByTc) " + "FROM Document " + "WHERE LOWER(documentText) LIKE CONCAT('%', :text, '%')") List<DocumentDTO> findByDocument(@Param("text") String text); // 调用时传入小写后的参数 documentRepository.findByDocument(text.toLowerCase());
方法2:将通配符拼接移到Java层
直接在Java层拼接%通配符,简化JPQL语句:
// Repository层代码 @Query("SELECT new com.hakstudio.archiveapp.dto.DocumentDTO(id, name, accessAuth, uploadedDate, uploadedBy, uploadedByTc, editedBy, editedByTc) " + "FROM Document " + "WHERE LOWER(documentText) LIKE :text") List<DocumentDTO> findByDocument(@Param("text") String text); // 调用时拼接通配符并转小写 documentRepository.findByDocument("%" + text.toLowerCase() + "%");
方法3:使用CAST函数显式转换(针对部分Hibernate版本)
如果前两种方法无效,可以尝试用JPQL的CAST函数显式转换参数类型:
@Query("SELECT new com.hakstudio.archiveapp.dto.DocumentDTO(id, name, accessAuth, uploadedDate, uploadedBy, uploadedByTc, editedBy, editedByTc) " + "FROM Document " + "WHERE LOWER(documentText) LIKE CONCAT('%', LOWER(CAST(:text AS string)), '%')") List<DocumentDTO> findByDocument(@Param("text") String text);
解释:错误提示中的STRING是JPQL定义的类型,java.lang.String是Java类型,正常情况下Hibernate会自动完成映射,出现该问题大概率是参数绑定的语法细节或特定Hibernate版本的小bug,上述方法都能解决该问题。
内容的提问来源于stack exchange,提问作者HAK
相关产品推荐
相关产品推荐

