Запрошено неизвестное преобразование переноса: 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)
Надеюсь, этот подход может оказаться полезным.