Я использую www.modelmapper.org и работаю над отображением одного и того же "плоского" Java DTO в несколько "иерархических "DTO.
" Плоский "DTO имеет ряд примитивных свойств.
" Иерархический "имеет ряд сложных типов, которые содержат ряд примитивных типов. Эти DTO очень похожи, но не одинаковы.
"Плоский" DTO:
class TransactionRequest
{
String cashierNumber;
Long amount;
Integer currency;
public String getCashierNumber {..
...
}
"Иерархические DTO:
class PurchaseRequest
{
POSInfo posInfo;
Amount amount;
...
public PosInfo getPosInfo {..
public Amount getAmount { ..
...
}
class CancelRequest
{
POSInfo posInfo;
Amount amount;
...
public PosInfo getPosInfo {..
public Amount getAmount { ..
...
}
class Amount
{
BigDecimal value;
Integer currency;
public Integer getCurrency{..
...
}
class PosInfo
{
String cashierNumber;
public String getCashierNumber {..
}
TransactionRequest должен отображаться в 1) PurchaseRequest и 2) CancelRequest.
Одна из проблем заключается в том, что сумма должна быть преобразована из Long (в второстепенных единицах) в BigDecimal (в основных единицах с десятичными цифрами). Я добился этого, написав свой собственный конвертер Long to BigDecimal. Теперь у меня есть проблема определить отображения, необходимые для многократного использования. Чего я не хочу, так это определять сопоставления для каждого целевого типа следующим образом:
class PurchaseMap extends PropertyMap<..
protected void configure()
{
using(new LongToBigDecimalConverter(...)).map().getAmount().setValue(source.getAmount());
...
}
class CancelMap extends PropertyMap<..
protected void configure()
{
using(new LongToBigDecimalConverter(...)).map().getAmount().setValue(source.getAmount());
...
}
Я хотел бы только один раз определить сопоставление Amount DTO (и всех других сопоставлений подтипов, таких как PosInfo и многие другие), а затем повторно использовать эти сопоставления. Я попробовал несколько вариантов:
Первое, что я попробовал, - это объявить отображение TransactionRequest на Amount DTO в моем ModelMapper. Во-первых, я предположил, что простого объявления этого сопоставления будет достаточно, чтобы механизм сопоставления также был задействован при сопоставлении TransactionRequest с PurchaseRequest. Однако это не так.
Второе, что я попробовал, работает, но кажется слишком сложным:
- Я создал PropertyMap для сопоставления TransactionRequest с Amount.
- Я создал собственный конвертер TransactionRequest в Amount. Конструктору этого конвертера требуется ModelMapper. ModelMapper, который я передаю конструктору, - это ModelMapper, который создал PropertyMap из 1)
- Я использую этот конвертер в PropertyMaps для PurchaseRequest и CancelRequest.
Вот код:
public class AmountMap extends PropertyMap<TransactionRequest , Amount>
{
....
protected void configure()
{
using(new LongToBigDecimalConverter(...)).map().getAmount().setValue(source.getAmount());
}
...
}
}
public class TransactionRequestToAmountConverter extends AbstractConverter<TransactionRequest, Amount>
{
private final ModelMapper mapper;
public TransactionRequestToAmountConverter(ModelMapper mapper)
{
this.mapper = mapper;
}
public Amount convert(TransactionRequest transactionRequest)
{
return mapper.map(transactionRequest, Amount.class);
}
}
public class PurchaseRequestMap extends PropertyMap<TransactionRequest, PurchaseRequest>
{
private final ModelMapper mapper;
public PurchaseRequestMap(ModelMapper mapper)
{
this.mapper = mapper;
}
protected void configure()
{
using(new TransactionRequestToAmountConverter(mapper)).map(source).setAmount(null);
...
}
}
Есть ли кто-нибудь, кто знает более простой подход к этому?