java mapstruct 1.3.1 игнорировать свойство в списке для двунаправленного отображения DTO - PullRequest
1 голос
/ 10 марта 2020

Я борюсь с проблемой зависимости от цикла в MapStruct. Я продолжаю иметь ошибку StackOverFlow из-за циклических зависимостей. Чтобы избежать этого, мне просто нужно исключить свойство List. Я нашел это: https://github.com/mapstruct/mapstruct/issues/933 Я глубоко просмотрел inte rnet и был удивлен, что не смог найти ни одного полного примера, показывающего двунаправленное отображение DTO с MapStruct (кроме использования @Context CycleAvoidingMappingContext, не работает для меня).

[EDIT]: я нашел обходной путь благодаря чату MapStruct, я добавляю его в EditorMapper

Вот мой случай Я думаю, довольно часто: у меня есть 2 DTO, ссылающихся друг на друга:

public class BookDTO {

    private Long id;

    private String title;

        //... other properties

    //@JsonManagedReference --> not necessary anymore
    private EditorDTO editor;
}
public class EditorDTO {

    private Long id;
    private String name;

        //...other properties

    //@JsonBackReference --> not necessary anymore
    private List< BookDTO > bookList;
}

И мне нужно, чтобы MapStruct мог исключить Редактор свойств из BookList в Редакторе, а затем избежать бесконечного l. oop. Вот что у меня сейчас есть в качестве картографов:

@Mapper
public interface BookMapper {

    BookMapper INSTANCE = Mappers.getMapper( BookMapper.class );

    @Mapping( target = "editor.bookList", ignore = true)
    BookDTO toDTO( BookEntity bookEntity );

    @Named( "NoEditor" )
    @Mapping(target = "editor", ignore = true)
    BookDTO toDTONoEditor( BookEntity bookEntity );

    List<BookDTO> toDTOList( List<BookEntity> bookEntityList );

    @Named( "NoEditor" )
    @IterableMapping(qualifiedByName="NoEditor")
    List<BookDTO> toDTOListNoEditor( List<BookEntity> bookEntityList );

    @Mapping( target = "editor.bookList", ignore = true)
    BookEntity toEntity( BookDTO bookDTO );

    List<BookEntity> toEntityList( List<BookDTO> bookDTOList );
}
@Mapper(uses = BookMapper.class)
public interface EditorMapper {

    EditorMapper INSTANCE = Mappers.getMapper( EditorMapper.class );

    @Named( "NoEditor" )
    @Mapping(target = "bookList", qualifiedByName = "NoEditor")
    EditorDTO toDTO( EditorEntity editorEntity );

    @Named( "NoEditor" )
    @IterableMapping(qualifiedByName="NoEditor")
    List<EditorDTO> toDTOList( List< EditorEntity > editorEntityList );

    EditorEntity toEntity( EditorDTO editorDTO );

    List<EditorEntity> toEntityList( List< EditorDTO > editorDTOList );
}

[РЕДАКТИРОВАТЬ]: теперь это работает, но не на 100% чисто (см. Ответ, который я отправил для более подробной информации)

Я также пробовал этот метод в картостроителях, но он не оказал никакого влияния на мою личность.

BookDTO toDTO( BookEntity bookEntity, @Context CycleAvoidingMappingContext context );

Кто-нибудь знает, что я делаю неправильно? БОЛЬШОЕ СПАСИБО! :)

1 Ответ

1 голос
/ 11 марта 2020

[РЕДАКТИРОВАТЬ]: Я добавляю решение для двунаправленного картирования ManyToMany Благодаря https://gitter.im/mapstruct/mapstruct-users# я смог получить решение. [РЕДАКТИРОВАТЬ]: У меня все еще были ошибки, которые я не осознавал. Теперь это исправлено в этом обновлении. Мне пришлось: - добавить uses атрибут EditorMapper: @Mapper(componentModel = "spring", uses = BookMapper.class) - добавить альтернативные методы, такие как toDTONoEditor или toDTOListNoEditor в BookMapper, где я игнорирую editor имущество. - отобразить эти альтернативные методы в EditorMapper - то же самое для каждой циклической зависимости

Вот решение:

BookDTO

public class BookDTO {

    private Long id;

    private String title;

        //... other properties

    private EditorDTO editor;
    private List< CategoryDTO > categoryList;
}

EditorDTO

public class EditorDTO {

    private Long id;
    private String name;

        //...other properties

    private List< BookDTO > bookList;
}

Категория DTO

public class CategoryDTO {

    private Long id;

    private String category;

    private List< BookDTO > bookList;
}

BookMapper

@Mapper(componentModel = "spring", uses = {CategoryMapper.class, EditorMapper.class})
public interface BookMapper {


    @Named( "NoBook" )
    @Mappings( {
            @Mapping(target = "categoryList", qualifiedByName = "NoBook"),
            @Mapping( target = "editor.bookList", ignore = true)
    } )
    BookDTO toDTO( BookEntity bookEntity );

    @Named( "NoEditor" )
    @Mappings( {
            @Mapping(target = "editor", ignore = true),
            @Mapping(target = "categoryList", qualifiedByName = "NoBook")
    } )
    BookDTO toDTONoEditor( BookEntity bookEntity );

    @Named( "NoCategory" )
    @Mappings( {
            @Mapping(target = "categoryList", ignore = true),
            @Mapping(target = "editor", qualifiedByName = "NoBook")
    } )
    BookDTO toDTONoCategory( BookEntity bookEntity );


    @Named( "NoBook" )
    @IterableMapping(qualifiedByName="NoBook")
    List<BookDTO> toDTOList( List<BookEntity> bookEntityList );

    @Named( "NoEditor" )
    @IterableMapping(qualifiedByName="NoEditor")
    List<BookDTO> toDTOListNoEditor( List<BookEntity> bookEntityList );

    @Named( "NoCategory" )
    @IterableMapping(qualifiedByName="NoCategory")
    List<BookDTO> toDTOListNoCategory( List<BookEntity> bookEntityList );


    @Named( "NoBook" )
    @Mappings( {
            @Mapping(target = "categoryList", qualifiedByName = "NoBook"),
            @Mapping( target = "editor.bookList", ignore = true)
    } )
    BookEntity toEntity( BookDTO bookDTO );

    @Named( "NoCategory" )
    @Mapping(target = "categoryList", ignore = true)
    BookEntity toEntityNoCategory( BookDTO bookDTO );


    @Named( "NoBook" )
    @IterableMapping(qualifiedByName="NoBook")
    List<BookEntity> toEntityList( List<BookDTO> bookDTOList );

    @Named( "NoCategory" )
    @IterableMapping(qualifiedByName="NoCategory")
    List<BookEntity> toEntityListNoCategory( List<BookDTO> bookDTOList );
}

EditorMapper

@Mapper(componentModel = "spring", uses = BookMapper.class)
public interface EditorMapper {

    @Named( "NoEditor" )
    @Mapping(target = "bookList", qualifiedByName = "NoEditor")
    EditorDTO toDTO( EditorEntity editorEntity );

    @Named( "NoBook" )
    @Mapping(target = "bookList", ignore = true)
    EditorDTO toDTONoBook( EditorEntity editorEntity );


    @Named( "NoEditor" )
    @IterableMapping(qualifiedByName="NoEditor")
    List< EditorDTO > toDTOList( List< EditorEntity > editorEntityList );

    @Named( "NoBook" )
    @IterableMapping(qualifiedByName="NoBook")
    List< EditorDTO > toDTOListNoBook( List< EditorEntity > editorEntityList );

    @Named( "NoBook" )
    @Mapping(target = "bookList", qualifiedByName = "NoBook")
    EditorEntity toEntity( EditorDTO editorDTO );

    @Named( "NoBook" )
    @IterableMapping(qualifiedByName="NoBook")
    List< EditorEntity > toEntityList( List< EditorDTO > editorDTOList );
}

CategoryMapper

@Mapper(componentModel = "spring",uses = BookMapper.class)
public interface CategoryMapper {


    @Named( "NoCategory" )
    @Mapping(target = "bookList", qualifiedByName = "NoCategory")
    CategoryDTO toDTO( CategoryEntity categoryEntity );

    @Named( "NoBook" )
    @Mapping(target = "bookList", ignore = true)
    CategoryDTO toDTONoBook( CategoryEntity categoryEntity );


    @Named( "NoCategory" )
    @IterableMapping(qualifiedByName="NoCategory")
    List<CategoryDTO> toDTOList( List< CategoryEntity > categoryEntityList );

    @Named( "NoBook" )
    @IterableMapping(qualifiedByName="NoBook")
    List<CategoryDTO> toDTOListNoBook( List< CategoryEntity > categoryEntityList );


    @Named( "NoCategory" )
    @Mapping(target = "bookList", qualifiedByName = "NoCategory")
    CategoryEntity toEntity( CategoryDTO categoryDTO );

    @Named( "NoBook" )
    @Mapping(target = "bookList", ignore = true)
    CategoryEntity toEntityNoBook( CategoryDTO categoryDTO );


    @Named( "NoCategory" )
    @IterableMapping(qualifiedByName="NoCategory")
    List<CategoryEntity> toEntityList( List< CategoryDTO > categoryDTOList );

    @Named( "NoBook" )
    @IterableMapping(qualifiedByName="NoBook")
    List<CategoryEntity> toEntityListNoBook( List< CategoryDTO > categoryDTOList );

}

Таким образом, круговая зависимость нарушается до того, как достигает бесконечной l oop. Однако это удовлетворяет на 99%, потому что объекты Editor и Book не идеально чисты. Editor содержит bookList, хорошо. Но каждая книга в bookList все еще содержит нулевое поле editor. И наоборот для объекта Book. Но, похоже, это проблема де / сериализации, а не проблема MapStruct. Вот Json получившийся

Редактор

{
  "id": 1,
  "name": "Folio",
  "coordinates": null,
  "bookList": [
    {
      "id": 1,
      "title": "Le cycle de Fondation, I : Fondation",
      "categoryList": [
        {
          "id": 5,
          "category": "LITERATURE&FICTION"
        }
      ],
      "language": "French",
      "isbn": 2070360539,
      "publicationDate": null,
      "numberOfPages": 416,
      "authorList": [],
      "libraryList": [
        {
          "id": 2,
          "name": "Library2",
          "coordinates": null
        },
        {
          "id": 1,
          "name": "Library1",
          "coordinates": null
        }
      ],
      "editor": null
    }
  ]
}

Книга

{
  "id": 1,
  "title": "Le cycle de Fondation, I : Fondation",
  "categoryList": [
    {
      "id": 5,
      "category": "LITERATURE&FICTION",
      "bookList": null
    }
  ],
  "language": "French",
  "isbn": 2070360539,
  "publicationDate": null,
  "numberOfPages": 416,
  "authorList": [],
  "libraryList": [
    {
      "id": 2,
      "name": "Library2",
      "coordinates": null
    },
    {
      "id": 1,
      "name": "Library1",
      "coordinates": null
    }
  ],
  "editor": {
    "id": 1,
    "name": "Folio",
    "coordinates": null,
    "bookList": null
  }
}

Категория

{
  "id": 1,
  "category": "CHILDREN",
  "bookList": [
    {
      "id": 5,
      "title": "Le petit prince",
      "categoryList": null,
      "language": "French",
      "isbn": 9782070612758,
      "publicationDate": null,
      "numberOfPages": 120,
      "authorList": [],
      "libraryList": [
        {
          "id": 2,
          "name": "Library2",
          "coordinates": null
        },
        {
          "id": 1,
          "name": "Library1",
          "coordinates": null
        }
      ],
      "editor": null
    }
  ]
}

Надеюсь, эта помощь:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...