мы столкнулись с одной проблемой. В нашем коде, который работает как минимум год, мы используем весенние репозитории с пользовательскими методами запросов, используя аннотацию @Query. В этих методах мы склонны применять фильтры к запросам на основе переданных в @Nullable параметров. До сих пор это работало хорошо, для запросов вроде этого:
@Query(value =
"select p FROM PersonOfInterestEntity p "
+ "where (?1 is null or p.upperPoiIdentifier like ?1) "
+ "and p.status in ?2 "
+ "and (?3 is null or p.createdDtm >= ?3) "
+ "and (?4 is null or p.createdDtm <= ?4) "
+ "and p.ixTenant.id=?5 ")
Page<PersonOfInterestEntity> findAllByNamesAndDateRangeAndStatusesAndTenantId(
@Nullable String identifier, List<StatusEnum> statuses, @Nullable Timestamp startDate, @Nullable Timestamp endDate, String tenantId, Pageable pageable);
Как указано в статьях по net, это удобный способ иметь метод с единым дао, который можно использовать для запроса с различными фильтрами, и пропустить условия для определенных столбцов в случае, если значения, переданные в NULL. Но проблема в том, что как только мы перешли на hibernate 5.4.10.Final (мы использовали hibernate 5.2.8.Final до сих пор), мы внезапно начали получать ошибку:
[ WARN] [ org.hibernate.engine.jdbc.spi.SqlExceptionHelper] - SQL Error: 932, SQLState: 42000
[ERROR] [ org.hibernate.engine.jdbc.spi.SqlExceptionHelper] - ORA-00932: inconsistent datatypes: expected TIMESTAMP got BINARY
Проблема в том, что это не только спящий режим что обновлено, но также и куча зависимостей, которые мы получаем от какой-то сторонней команды - поэтому мы не можем утверждать, что именно Hibernate является тем, что имеет значение здесь. Кроме того, мы не можем уменьшить версию Hibernate до версии 5.2.8 в обновленном коде, а также мы не можем увеличить версию Hibernate в старом коде, который прекрасно работает с этими запросами, поскольку в обоих случаях мы получаем некоторые проблемы с запуском -> которые затрудняют изоляцию что на самом деле вызывает это изменение поведения. Интересно, что тот же синтаксис все еще работает для параметров типа String (см.? 1 сразу после ключевого слова в запросе), проблема связана только с меткой времени.
Мой вопрос заключается в том, стоит ли нам смотреть на изменение в спящем режиме , spring-data-jpa или Oracle драйвер? Я не смог найти никаких документов, которые бы указывали на такую обратную несоответствие. Мы действительно хотели бы пропустить необходимость обходного пути, чтобы разделить наши методы, чтобы разделить запросы для каждого нулевого / ненулевого параметра, поскольку это действительно увеличило бы беспорядок в коде, так как у нас есть много комбинаций этих необязательных параметров. А также хотел бы понять, как это работает до сих пор, и почему метка времени отличается от других типов.
update: Я только что понял, что у нас также есть некоторый специальный класс, который влияет на то, как метки времени в коде сериализуются в базу данных. Из-за запланированного порта на MySql было необходимо округлить время в дБ на 3/100 мс, поэтому у нас есть UserType, который должен быть ответственным за это. Это может как-то повлиять на привязку параметров запроса, не уверен ... Отладка кода гибернации (что довольно сложно, поскольку он не попадает в стек вызовов потоков в IDE), я заметил, что PreparedStatementParameter для части запроса выглядит следующим образом: p.createdDtm >= ?3
, получает внутренний ожидаемый тип как CustomType с именем того специального класса, который был добавлен. часть запроса для параметра с тем же индексом: ?3 is null
, разрешается без ожидаемого типа, что позже разрешается в привязке как (sqlTypeDescriptior = VarbinaryTypeDescriptor и javaTypeDescriptor = SerializableTypeDescriptor), а затем приводит к ошибке, которую я дал выше. Но также стоит сказать, что код, который корректирует значения меток времени, уже существовал в предыдущей версии кода, который нормально работал на hibernate 5.2.8 ... Может быть, этот пользовательский тип требует некоторых настроек для более новых версий hibernate?