Запрошено неизвестное преобразование переноса: java.util.ImmutableCollections$Set12 в java.lang.String

После перехода с Spring-data-jpa 2.7.1 на 3.1.2 (миграция SpringBoot 3.1.2) в методе:

      @Query("""
    SELECT o
    FROM Storage o
    WHERE o.status = 'SUCCESS'
    AND (
        (:referenceNumbers) IS NULL
        OR o.referenceNumber IN (:referenceNumbers)
    )
    ...
""")
Page<Storage> findObject(ObjectFilter filter, Set<String> referenceNumbers, Iterable<Long> systemIds, Pageable pageable);
      @Entity
@Getter
@Setter
@RequiredArgsConstructor
@EqualsAndHashCode
@Accessors(chain = true)
class Storage {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String referenceNumber;

    @Enumerated(EnumType.STRING)
    private Status status;
}

Я получаю:

org.springframework.orm.jpa.JpaSystemException: запрошено неизвестное преобразование оболочки: java.util. ImmutableCollections$Set12 в java.lang.String : org.hibernate.type.descriptor.java.StringJavaType(java.lang.String)

Похоже, метод больше не может обрабатывать коллекцию.

Я пытался найти документацию по методу JPQL, но не смог найти ничего подходящего.

Для Spring Data JPA 2.7.1 этот метод работал отлично.

Я пытался найти документацию поINметод для Spring Data JPA 3.1.2, поскольку у меня в проекте много подобных методов, и мое приложение может работать со многими базами данных (PostgreSQL, Oracle).

2 ответа

Похоже,(:referenceNumbers) IS NULLв этом проблема. Вы можете разделить метод запроса на два метода, один из которых имеет собственную логику для его обработки:

      @Query("SELECT o FROM Storage o WHERE o.status = 'SUCCESS' " +
" AND (:ignoreReferenceNumbers OR o.referenceNumber IN (:referenceNumbers)) " +"...")
Page<Storage> findObjectInternal(ObjectFilter filter, Set<String> referenceNumbers, boolean ignoreReferenceNumbers, Iterable<Long> systemIdsPageable pageable);

default Page<Storage> findObject(ObjectFilter filter, Set<String> referenceNumbers, Iterable<Long> systemIds,Pageable pageable){
    if(referenceNumbers==null){
        return findObjectInternal(filter, Collections.emptyList(), true, systemIds, pageable);
    }
    return findObjectInternal(filter, referenceNumbers, false, systemIds, pageable);
}

или используйте два (перегруженных)defaultметоды:

      @Query("SELECT o FROM Storage o WHERE o.status = 'SUCCESS' " +
" AND (:ignoreReferenceNumbers OR o.referenceNumber IN (:referenceNumbers)) " +"...")
Page<Storage> findObjectInternal(ObjectFilter filter, Set<String> referenceNumbers, boolean ignoreReferenceNumbers, Iterable<Long> systemIdsPageable pageable);

default Page<Storage> findObject(ObjectFilter filter, Set<String> referenceNumbers, Iterable<Long> systemIds,Pageable pageable){
    return findObjectInternal(filter, referenceNumbers, false, systemIds, pageable);
}

default Page<Storage> findObject(ObjectFilter filter, Iterable<Long> systemIds,Pageable pageable){
    return findObjectInternal(filter, Collections.emptyList(), true, systemIds, pageable);
}

и всегда вызывайте соответствующий метод по умолчанию вместо использованияnullаргумент. Как упоминалось ОП в комментариях , это также возможно так:

      @Query("SELECT o FROM Storage o WHERE o.status = 'SUCCESS' " +
" AND (coalesce(:#{#referenceNumbers}, null) IS NULL OR o.referenceNumber IN (:referenceNumbers)) " +"...")
Page<Storage> findObject(ObjectFilter filter, Set<String> referenceNumbers, Iterable<Long> systemIds,Pageable pageable);

Я тоже столкнулся с этой проблемой, но я провел тщательную проверку, и эта ошибка возникает, потому что, например, когда:listNameявляетсяnull, Весна JPA@Queryобнаруживает это и автоматически преобразует этот параметр вString.

Чтобы предотвратить это, я использовал этот подход, как в примере ниже, используяCoalesce:

      select u from product u where  (Coalesce(:listProductName) is null or u.productName in :listProductName)

Надеюсь, этот подход может оказаться полезным.

Другие вопросы по тегам