2017-01-15 7 views
0

Почему это не генерирует код сопоставления автоматически, когда информация о сопоставлении явно передается Mapstruct второй функцией отображения?Map flat object to compos object with mapstruct

Flat   Composed 
----   -------- 
- String a - String a 
       - Sub 
- String b  - String b 
- String c  - String c 

.

@Mapper(uses = SubToFlatMapper.class) 
public interface ComposedToFlatMapper { 

    Flat map(Composed c); // Unmapped target properties: "b, c". 
          // Not OK because Sub mapping is defined in 
          // SubToFlatMapper and is used here :(
} 

@Mapper 
public interface SubToFlatMapper { 

    Flat map(Sub s); // Unmapped target properties: "a". 
        // (OK because 'a' is not in Sub) 
} 

Использование для ясности:

Composed composed = new Composed(); 
Sub sub = new Sub(); 

composed.setA("A"); 
composed.setSub(sub); 

sub.setB("B"); 
sub.setC("C"); 

Flat flat = ComposedToFlatMapper.INSTANCE.map(composed); 

// flat.getA() is "A", OK! 
// flat.getB() is null, unexpected, should be "B" 
// flat.getC() also null, should be "C". 

"B" и "C" не отображаются в flat, поскольку генерировать код не создает метод для этого.

Я думал, что предоставил необходимую информацию о генераторе. Он должен генерировать внутри ComposedToFlatMapperImpl, когда он видит метод Flat map(Sub s).

Edit:

Я не упоминал об этом раньше, но в оригинале вопрос, который я мог бы также использовать update -методов, которые являются более гибкими.

Теперь, если есть новый тип Sub2. :

@Mapper(uses = {SubToFlatMapper.class, Sub2ToFlatMapper.class}) 
public interface ComposedToFlatMapper { 

    Flat map(Composed c); 

    void update(Composed source, @MappingTarget Flat target); 
} 

@Mapper 
public interface SubToFlatMapper { 

    Flat map(Sub s); 

    void update(Sub source, @MappingTarget Flat target); 
} 

@Mapper 
public interface Sub2ToFlatMapper { 

    Flat map(Sub2 s); 

    void update(Sub2 source, @MappingTarget Flat target); 
} 

.

Flat   Composed 
----   -------- 
- String a - String a 
       - Sub 
- String b  - String b 
- String c  - String c 
       - Sub2 
       - String d 
       - String e 

С Flat имеет не Sub2 ссылки просто игнорировать его. Нет необходимости генерировать код преобразования.

+0

Ваш метод отображения имеет 'Composed' в качестве параметра и' Flat' в качестве цели; это то, что вы на самом деле имели в виду, или это должно быть наоборот (как подразумевается именем класса mapper)? – Gunnar

+0

Я добавил случай использования – aliopi

+0

Я исправил имена классов. Надеюсь, теперь лучше читать. – aliopi

ответ

1

Вы можете просто выровнять структуру вложенной источника следующим образом:

@Mapper 
public interface ComposedToFlatMapper { 

    @Mapping(target="b", source="sub.b") 
    @Mapping(target="c", source="sub.c") 
    Flat map(Composed c); 
} 
+0

Да, но это избыточная информация. Генератор должен увидеть отображение типа 'Sub' и использовать его. В другом случае мне не нужна конфигурация 'uses ='. Это настолько очевидно, что я не думаю, что вы этого не видите. – aliopi

+0

Когда Mapstruct начинает сопоставлять тип «Составленный» и видит тип «Sub», он должен использовать/делегировать метод «Плоская карта (Sub s)» из «SubToFlatMapper», иначе композиционная модель Mapstruct будет нарушена, если она заставит мне указать жестко скопированные сопоставления. Эта последняя миля делает его гением ИМХО. – aliopi

+0

Это не то, как он работает, и я не уверен, что вы предлагаете сделать на самом деле. Предположим, что был 'Sub2' с' d' и 'e', а другой использовался mapper' Sub2ToFlatMapper'. Какой метод, 'subToFlat()' или 'sub2ToFlat()', должен вызываться, чтобы получить экземпляр 'Flat' для возврата из' createdToFlat() '? – Gunnar