Код: Выделить всё
ID("id"),
NAME("name"),
START_DATE("start_date"),
END_DATE("end_date"),
TYPE("type"),
CREATED_AT("created_at");
private final String column;
public static RowMapper getEventDTORowMapper() {
return (rs, rowNum) -> EventDTO.builder()
.id(rs.getInt(EventRowMapper.ID.column))
.name(rs.getString(EventRowMapper.NAME.column))
.startDate(rs.getDate(EventRowMapper.START_DATE.column))
.endDate(rs.getDate(EventRowMapper.END_DATE.column))
.type(rs.getString(EventRowMapper.TYPE.column))
.createdAt(rs.getDate(EventRowMapper.CREATED_AT.column))
.build();
}
Я провел рефакторинг кода, представив более общую утилиту сопоставления (RowMapperUtils). Эта утилита использует отражение для сопоставления значений ResultSet с DTO на основе полей и типов, определенных в перечислении (EventRowMapper). Я реализовал интерфейс ColumnMapper, который стандартизирует структуру сопоставления, что делает код более удобным в сопровождении и позволяет повторно использовать его в нескольких DTO.
Новый подход:
Код: Выделить всё
@Getter
@AllArgsConstructor
public enum EventRowMapper implements ColumnMapper {
ID("id", "id", DataType.INTEGER),
NAME("name", "name", DataType.STRING),
START_DATE("start_date", "startDate", DataType.DATE),
END_DATE("end_date", "endDate", DataType.DATE),
TYPE("type", "type", DataType.STRING),
CREATED_AT("created_at", "createdAt", DataType.DATE);
private final String column;
private final String field;
private final DataType type;
public static RowMapper getEventDTORowMapper() {
return (rs, rowNum) -> RowMapperUtils.mapResultSetToDTO(rs, EventDTO.class, List.of(EventRowMapper.values()));
}
}
Код: Выделить всё
public static T mapResultSetToDTO(ResultSet rs, Class dtoClass, List columns) {
try {
T dto = dtoClass.getDeclaredConstructor().newInstance();
for (ColumnMapper c : columns) {
Field field = dtoClass.getDeclaredField(c.getField());
field.setAccessible(true); // To prevent IllegalAccessException
field.set(dto, getValueFromResultSet(rs, c));
}
return dto;
} catch (Exception e) {
log.error("Failed to map ResultSet to DTO", e);
throw new RuntimeException("Failed to map ResultSet to DTO");
}
}
private static Object getValueFromResultSet(ResultSet rs, ColumnMapper c) throws SQLException {
switch (c.getType()) {
case INTEGER: return rs.getInt(c.getColumn());
case DATE: return rs.getDate(c.getColumn());
case DOUBLE: return rs.getDouble(c.getColumn());
case BOOLEAN: return rs.getBoolean(c.getColumn());
default: return rs.getString(c.getColumn()); // String will be used here
}
}
Хотя этот подход повышает гибкость и удобство обслуживания, меня беспокоит потенциальная производительность. влияние использования отражения для динамического сопоставления полей. В сценариях, где производительность имеет решающее значение (например, запросы большого объема), может ли это универсальное решение привести к увеличению накладных расходов по сравнению с более явным подходом к сопоставлению?
- Существует ли производительность компромиссы, которые мне следует учитывать при использовании отражения таким образом?
- Приемлем ли этот подход для промышленного использования в высокопроизводительных приложениях?
- Существуют ли какие-либо альтернативные методы или структуры, которые мне следует рассмотреть для более эффективной обработки динамического картирования? Если да, то какие?
Подробнее здесь: https://stackoverflow.com/questions/790 ... c-approach