В настоящее время я работаю над переносом приложения Spring Boot с MariaDB на OracleDB.Бэкенд Spring / Java использует Hibernate / JPA для генерации запросов к базе данных MariaDB, и поэтому теоретически миграция должна быть довольно безболезненной.Измените диалект, и все готово.На практике оказывается, что спящий диалект для OracleDB 12C делает некоторые странные предположения, когда речь идет о привязке типов к типам баз данных.Бэкэнд все еще использует старый тип java.util.Date для всех своих дат, которые Hibernate, похоже, отчаянно хочет привести к типу Long (даже более устаревшему, насколько я мог найти) или к типу BLOB некоторого вида.BLOB-объекты - это, конечно, здорово, но кажется, что гораздо удобнее сопоставить дату с датой.Поскольку строка в настоящее время настроена на ожидание DATE, я получаю следующую ошибку, когда пытаюсь получить доступ к строке:
InvalidDataAccessResourceUsageException: could not extract ResultSet
ORA-00932: inconsistent datatypes: expected - got BLOB
Я пытался использовать функцию конвертера JPA, чтобы вручную привести эти объекты Date к чему-либо в Hibernate.не испортит, но это привело к тому, что Hibernate ожидал VARBINARY, как описано в этой статье: https://dzone.com/articles/leaky-abstractions-or-how-bind
@Converter(autoApply = false)
public class DateDATEAttributeConverter implements AttributeConverter<Date, DATE> {
@Override
public DATE convertToDatabaseColumn(Date date){
return new DATE(); // conversion to be done later
}
@Override
public Date convertToEntityAttribute(DATE date) {
return new Date(); // conversion to be done later
}
}
Использование этого очень минимального конвертера и пошаговое выполнение кода с помощью отладчика, показывает, что, похоже, все правильно подключено к подготовленному заявлению, но Hibernate отклоняет его с помощью org.hibernate.exception.SQLGrammarException: не удалось извлечь ошибку ResultSet.
После этого я решил попробовать сделать пользовательский тип пользователякак в приведенной выше статье, и более подробно описано здесь: https://www.baeldung.com/hibernate-custom-types
В настоящее время я приводил java.util.Date к Oracle DATE с помощью этого пользовательского типа.Аннотация @Type используется для того, чтобы убедиться, что соответствующее поле преобразовано с помощью этой реализации CustomType.К сожалению, после реализации всего этого возвращается та же ошибка, что и раньше.Кажется, где-то под капотом все еще происходит преобразование / связывание, на которое я не смог повлиять.
@Override
public Object nullSafeGet(
ResultSet rs,
String[] names,
SessionImplementor session,
Object owner
)
throws SQLException {
LOGGER.debug("nullSafeGet: " + names[0]);
return rs.getTimestamp(names[0]);
}
@Override
public void nullSafeSet(
PreparedStatement st,
Object value,
int index,
SessionImplementor session
)
throws SQLException {
if(Objects.isNull(value)){
st.setNull(index, Types.DATE);
}else{
Date dateUtil = (Date)value;
LocalDate localDate = dateUtil.toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
java.sql.Date dateSQL = java.sql.Date.valueOf(localDate);
DATE date = new DATE(dateSQL);
LOGGER.debug("nullSafeSet: " + date);
st.setObject(index, date);
}
}
Есть ли какой-нибудь установленный способ обойти это?Я довольно долго искал в Интернете, но я не продвинулся дальше этих двух статей, или мне сказали прекратить использовать старые типы, такие как Date.К сожалению, с большими старыми проектами и новыми сроками, это не является предпочтительным вариантом.