Простой гибкий маппер
В приложении, которым я сейчас занимаюсь, существует несколько классов для представления
одной сущности. Например, у сущности “Сотрудник” есть целых три класса:
EmployeeDto
- для приема с сервера, Employee
- для работы в приложении,
EmployeeEntity
- для хранения в локальной базе. У нас есть naming conventions
, по которым
суффикс *Dto
говорит, что эта сущность будет использоваться
для передачи данных
по сети (скорее всего, такая сущность будет реализовывать
интерфейс Serializable
), суффикс *Entity
говорит, что эта сущность
будет использоваться для хранения в БД (у такой сущности будет
много аннотаций для ORM), а сущности без суффикса
используются непосредственно в бизнес логике, будем их называть доменными. Я расскажу
о выбранном мной способе конвертирования данных между такими сущностями.
Введем интерфейсы:
interface DtoOf<T> {
T dto();
}
interface EntityOf<T> {
T entity();
}
interface DomainOf<T> {
T domain();
}
Они очень простые, например, DtoOf
- интерфейс объектов, которые умеют
представлять что-то в DTO. И если у нас есть
доменная сущность Entity
, то, чтобы сделать из нее
DTO‘шку достаточно объекта такого класса:
class EmployeeDtoOfDomain<EmployeeDto> implements DtoOf<EmployeeDto> {
private final Employee employee;
public EmployeeDtoOfDomain(final Employee employee) {
this.employee = employee;
}
@Overrride
public EmployeeDto dto() { ... }
}
...
final EmployeeDto dto = new EmployeeDtoOfDomain(entity).dto();
Название класса EmployeeDtoOfDomain
говорит о том, что объект этого
класса - это маппинг доменной сущности сотрудника в его
DTO‘шку.
Такой подход не накладывает ограничения на то, из чего мы получаем
нужный нам объект после маппинга. То есть EmployeeEntity
мы можем
получить хоть из EmployeeDto
, или даже сразу из БД:
final EmployeeEntity entity = new EmployeeEntityOfDbConnection(
connection, employeeId).entity();
Получившиеся мапперы с помощью такого подхода занимаются только одной задачей: например, маппингом доменной сущности в DTO. И если нужно сделать обратный маппинг, то этим должен и будет заниматься другой объект.