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

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

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

@Query(value = "SELECT " +
            "   summaries.event_type as \"eventType\", " +
            "   summaries.institution_id as \"institutionId\", " +
            "   identifiers.id as \"studentIdentifierId\", " +
            "   identifiers.name as \"studentIdentifierName\" " +
            "FROM summaries " +
            "LEFT JOIN roles ON summaries.student_id=roles.id " +
            "LEFT JOIN identifiers ON roles.identifier_id=identifiers.id " +
            "WHERE " +
            "   summaries.student_id IS NOT NULL AND " +
            "   summaries.event_type IN (:eventTypes) AND " +
            "   (:identifierId IS NULL OR roles.identifier_id=:identifierId) " +
            "GROUP BY " +
            "   summaries.institution_id, " +
            "   summaries.student_id, " +
            "   identifiers.id, " +
            "   identifiers.name, " +
            "   summaries.event_type",
            nativeQuery = true)
    List<CustomProjection> findByCustomCondition(
            @Param("identifierId") Long identifierId,
            @Param("eventTypes") List<String> eventTypes);

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

InvalidDataAccessResourceUsageException: could not extract ResultSet; SQL [n/a]; nested exception is org.hibernate.exception.SQLGrammarException: could not extract ResultSet.
Caused by: org.postgresql.util.PSQLException: ERROR: operator does not exist: bigint = bytea
  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) ),但没有起到任何作用。
另外,这是一个遗留项目,所以我使用以下版本:

compile group: 'org.springframework.data', name: 'spring-data-jpa', version: '1.11.6.RELEASE'
compile group: 'org.postgresql', name: 'postgresql', version: '42.2.2'
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 允许显式指定绑定参数类型:

import org.hibernate.type.LongType;

// ...

List<CustomProjection> results = entityManager.createNamedQuery("find_by_custom_condition" )
.unwrap(org.hibernate.query.Query.class)
.setParameter("identifierId", identifierId, LongType.INSTANCE)
.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替您实现。在实现中,您必须这样做

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

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

相关问题