Oracle DB запрашивает через JPA / Hibernate от java.util.Date - PullRequest
0 голосов
/ 28 января 2019

В настоящее время я работаю над переносом приложения 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.К сожалению, с большими старыми проектами и новыми сроками, это не является предпочтительным вариантом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...