Mapstruct: автоматическое увеличение переменной объекта в списке объектов

У меня есть несколько POJO, как это:

@Data
public class A {
    List<B> bList;
}

@Data
public class B {
    int id;
    int x;
}

@Data
public class C {
    List<D> dList;
}

@Data
public class D {
    int x;
}

Теперь я хочу отобразить класс C на класс A, используя MapStruct, чтобы значение id в bList в классе A автоматически увеличивалось. Я использую Mapstruct 1.1.0.Final.

Для картирования List<D> в List<B>Я могу определить маппер для class B а также class D и POJO будут автоматически отображаться, но я не смог найти способ сопоставления POJO с автоматическим приращением в поле.

Мой POJO очень большой. Есть ли способ в Map Struct для автоинкрементных переменных в списке?

1 ответ

Решение

У вас есть 2 варианта сделать это с 1.1.0.Final и еще один вариант с 1.2.0.Beta2.

Первый вариант при картировании D в B

Ты можешь использовать @AfterMapping между D а также B и использовать ThreadLocal там.

public class AutoIncrementorThreadLocal {

    @AfterMapping
    public /*static*/ void autoIncrementId(D source, @MappingTarget B target) {
        //here you use the ThreadLocal and do something like getAndIncrement
    }
}

В вашем картографе вы должны будете сказать, что вы используете AutoIncrementorThreadLocal, Также метод может быть статическим, MapStruct также может вызывать статические методы.

Второй вариант при картировании C в A

public class AutoIncrementorBulk {

    @AfterMapping
    public /*static*/ void autoIncrementId(C source, @MappingTarget A target) {
        //here you iterate the list and increment the ids
    }
}

В вашем картографе вы должны будете сказать, что вы используете AutoIncrementorBulk, Также метод может быть статическим, MapStruct также может вызывать статические методы.

Третий вариант с 1.2.0.Beta2

Вы можете использовать новый @Context и имеют @AfterMapping в теме.

public class AutoIncrementorContext {

    private int counter = 0;
    @AfterMapping
    public void autoIncrementId(D source, @MappingTarget B target) {
        //here you use your counter, because you are only using this instance during one mapping
    }
}

Ваш картограф должен выглядеть так:

@Mapper
public interface MyMapper {

    C map(A source, @Context AutoIncrementorContext context);

    D map(B source, @Context AutoIncrementorContext context);
}

Когда вы собираетесь позвонить своему мапперу, вам нужно будет позвонить так:

myMapper.map(a, new AutoIncrementorContext());

Первый и третий подходы похожи с той лишь разницей, что вам не нужно использовать ThreadLocal (s) с третьим подходом.

Другие вопросы по тегам