spring数据带空参数的jpa本机查询(postgresql)

mitkmikd  于 2021-07-06  发布在  Java
关注(0)|答案(4)|浏览(396)

问题是如何使本机查询接受空参数?
我的问题是:

  1. @Query(value = "SELECT " +
  2. " summaries.event_type as \"eventType\", " +
  3. " summaries.institution_id as \"institutionId\", " +
  4. " identifiers.id as \"studentIdentifierId\", " +
  5. " identifiers.name as \"studentIdentifierName\" " +
  6. "FROM summaries " +
  7. "LEFT JOIN roles ON summaries.student_id=roles.id " +
  8. "LEFT JOIN identifiers ON roles.identifier_id=identifiers.id " +
  9. "WHERE " +
  10. " summaries.student_id IS NOT NULL AND " +
  11. " summaries.event_type IN (:eventTypes) AND " +
  12. " (:identifierId IS NULL OR roles.identifier_id=:identifierId) " +
  13. "GROUP BY " +
  14. " summaries.institution_id, " +
  15. " summaries.student_id, " +
  16. " identifiers.id, " +
  17. " identifiers.name, " +
  18. " summaries.event_type",
  19. nativeQuery = true)
  20. List<CustomProjection> findByCustomCondition(
  21. @Param("identifierId") Long identifierId,
  22. @Param("eventTypes") List<String> eventTypes);

现在当我经过的时候 identifierId 作为null,我接收到错误:

  1. InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet.
  2. Caused by: org.postgresql.util.PSQLException: ERROR: operator does not exist: bigint = bytea
  3. HINT: No operator matches the given name and argument types. You might need to add explicit type casts.

好像在排队 (:identifierId IS NULL OR roles.identifier_id=:identifierId) 在这里导致了一个问题,但实际上找不到一个好的解决方案,因为从我的理解来看,它应该正常工作(当我在pgadmin上直接使用这个查询时,它应该正常工作,所以我很确定这是一个与Map相关的问题)。
我试着把识别码( cast(:identifierId as bigint) ),但没有起到任何作用。
另外,这是一个遗留项目,所以我使用以下版本:

  1. compile group: 'org.springframework.data', name: 'spring-data-jpa', version: '1.11.6.RELEASE'
  2. compile group: 'org.postgresql', name: 'postgresql', version: '42.2.2'
  3. compile group: 'org.hibernate', name: 'hibernate-core', version: '5.2.17.Final'
uyhoqukh

uyhoqukh1#

通过添加空格来修改查询 roles.identifier_id=:identifierId 应该是这样的 roles.identifier_id= :identifierId

drkbr07n

drkbr07n2#

正如@coladict的回答中提到的,很不幸,您不能用cleanspringdatajpa解决方案来实现您想要的。因此,可以使用 EntityManager 和休眠特定 setParameter 允许显式指定绑定参数类型:

  1. import org.hibernate.type.LongType;
  2. // ...
  3. List<CustomProjection> results = entityManager.createNamedQuery("find_by_custom_condition" )
  4. .unwrap(org.hibernate.query.Query.class)
  5. .setParameter("identifierId", identifierId, LongType.INSTANCE)
  6. .getResultList();

那你可以用 @NamedNativeQuery@SqlResultSetMapping 将本机查询结果Map到 CustomProjection . 请参阅hibernate文档中的示例。
另请参阅这篇关于 setParameter 在jpa和hibernate查询中的用法。

oyxsuwqo

oyxsuwqo3#

您必须使用以下选项: (cast(:identifierId as bigint) IS NULL OR roles.identifier_id=:identifierId)

ukxgm1gy

ukxgm1gy4#

这是hibernate+postgresql的一个常见问题,解决方法是自己实现这个方法,而不是让spring替您实现。在实现中,您必须这样做

  1. List<CustomProjection> findByCustomCondition(
  2. @Param("identifierId") Long identifierId,
  3. @Param("eventTypes") List<String> eventTypes) {
  4. // entityManager is acquired with the @PersistenceContext annotation as an injectable
  5. Query q = entityManager.createNativeQuery(..., CustomProjection.class);
  6. // the important part:
  7. q.setParameter("identifierId", 0L);
  8. q.setParameter("identifierId", identifierId);
  9. ...

第一次呼叫 setParameter 确保hibenate使用正确的类型设置器,第二个调用在没有执行查询的情况下重写第一个值,并跳过类型检测。

相关问题