1 В избранное 0 Ответвления 0

OSCHINA-MIRROR/selfly-sonsure-dumper

Присоединиться к Gitlife
Откройте для себя и примите участие в публичных проектах с открытым исходным кодом с участием более 10 миллионов разработчиков. Приватные репозитории также полностью бесплатны :)
Присоединиться бесплатно
В этом репозитории не указан файл с открытой лицензией (LICENSE). При использовании обратитесь к конкретному описанию проекта и его зависимостям в коде.
Клонировать/Скачать
jdbc-type-converter.md 6.4 КБ
Копировать Редактировать Web IDE Исходные данные Просмотреть построчно История
gitlife-traslator Отправлено 28.11.2024 13:43 e04b5c0

Jdbc查询自定义 тип преобразователя

Описание

Обычно в этом нет необходимости, но Spring встроенный RowMapper может удовлетворить большинству сценариев.

История создания:

Приложение требует только облегчённой версии или демонстрационной среды, и при переключении базы данных на SQLite обнаруживается, что запрос не может нормально обрабатывать код типа LocalDateTime (тип базы данных — datetime), выдавая сообщение об ошибке:

org.springframework.beans.ConversionNotSupportedException: Failed to convert property value of type 'java.sql.Timestamp' to required type 'java.time.LocalDateTime' for property 'gmtLastLogin'; nested exception is java.lang.IllegalStateException: Cannot convert value of type 'java.sql.Timestamp' to required type 'java.time.LocalDateTime' for property 'gmtLastLogin': no matching editors or conversion strategy found

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

PS: Этот тип преобразования действует только тогда, когда результат запроса является объектом Bean, если это не объект Bean, прямое преобразование Object не имеет никакого эффекта.

Интерфейс описания

Содержит три метода, метод support определяет, применим ли он к текущему типу базы данных. Два оставшихся метода представляют собой взаимное преобразование между базой данных и Java.

/**
* @author selfly
*/
public interface JdbcTypeConverter {

    /**
     * Support dialect boolean.
     *
     * @param dialect the dialect
     * @return the boolean
     */
    boolean support(String dialect);

    /**
    * Db 2 java type object.
    *
    * @param dialect      the dialect
    * @param requiredType the required type
    * @param value        the value
    * @return the object
    */
    default Object db2JavaType(String dialect, Class<?> requiredType, Object value) {
        return value;
    }

    /**
    * Java 2 db type object.
    *
    * @param dialect the dialect
    * @param value   the value
    * @return the object
    */
    default Object java2DbType(String dialect, Object value) {
        return value;
    }

}

Реализация

Ниже представлена реализация совместимости с LocalDateTime для SQLite, которая может служить примером.

/**
 * @author selfly
 */
public class SqliteCompatibleLocalDateTimeConverter implements JdbcTypeConverter {

    private static final String LOCAL_DATE = "LocalDate";
    private static final String LOCAL_TIME = "LocalTime";
    private static final String LOCAL_DATE_TIME = "LocalDateTime";

    private static final String PATTERN_DATETIME = "yyyy-MM-dd HH:mm:ss";
    private static final String PATTERN_DATE = "yyyy-MM-dd";
            private static final String PATTERN_TIME = "HH:mm:ss";

    private final Set<String> types = new HashSet<>();

    public SqliteCompatibleLocalDateTimeConverter() {
        types.add(LOCAL_DATE);
        types.add(LOCAL_TIME);
        types.add(LOCAL_DATE_TIME);
    }

    @Override
    public boolean support(String dialect) {
        return DatabaseDialect.SQLITE.belong(dialect);
    }

    @Override
    public Object db2JavaType(String dialect, Class<?> requiredType, Object value) {
        if (types.contains(requiredType.getSimpleName()) && value instanceof Timestamp) {
            final LocalDateTime localDateTime = ((Timestamp) value).toLocalDateTime();
            if (LOCAL_DATE.equals(requiredType.getSimpleName())) {
                return localDateTime.toLocalDate();
            } else if (LOCAL_TIME.equals(requiredType.getSimpleName())) {
                return localDateTime.toLocalTime();
            } else {
                return localDateTime;
            }
        }
        return value;
    }

    @Override
    public Object java2DbType(String dialect, Object value) {
        if (value instanceof LocalDateTime) {
            return ((LocalDateTime) value).format(DateTimeFormatter.ofPattern(PATTERN_DATETIME));
        } else if (value instanceof LocalDate) {
            return ((LocalDate) value).format(DateTimeFormatter.ofPattern(PATTERN_DATE));
        } else if (value instanceof LocalTime) {
            return ((LocalTime) value).format(DateTimeFormatter.ofPattern(PATTERN_TIME));
        } else {
            return value;
        }
    }
}

По умолчанию этот JdbcTypeConverter уже добавлен, и он автоматически активируется, когда база данных является SQLite. Если вы вручную объявляете JdbcEngine, вам необходимо явно добавить его:

JdbcTemplateEngineConfigImpl jdbcTemplateEngineConfig = new JdbcTemplateEngineConfigImpl();
jdbcTemplateEngineConfig.setDataSource(getDataSource());
final List<JdbcTypeConverter> jdbcTypeConverters = Collections.singletonList(new SqliteCompatibleLocalDateTimeConverter());
jdbcTemplateEngineConfig.setJdbcTypeConverters(jdbcTypeConverters);
defaultJdbcEngine = new JdbcEngineImpl(jdbcTemplateEngineConfig);

Опубликовать ( 0 )

Вы можете оставить комментарий после Вход в систему

1
https://api.gitlife.ru/oschina-mirror/selfly-sonsure-dumper.git
git@api.gitlife.ru:oschina-mirror/selfly-sonsure-dumper.git
oschina-mirror
selfly-sonsure-dumper
selfly-sonsure-dumper
master