Обычно в этом нет необходимости, но 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 )