Search code examples
springmodelmapper

Issue mapping fields ModelMapper


I use DTO and modelMapper in order not to make visible some fields. I have a CategoryEntity that can have subcategories

public class CategoryEntity {

    @Id
    @GeneratedValue(strategy= GenerationType.IDENTITY)
    private Long id;

    @Column(length = 30, nullable = false)
    private String categoryKeyId;

    @Column(nullable = false)
    private String name;

    @ManyToOne(optional = true, fetch = FetchType.LAZY)
    @JoinColumn(name="parent_id", nullable=true)
    private CategoryEntity parentCategory;

    // allow to delete also subcategories
    @OneToMany(mappedBy="parentCategory", cascade = CascadeType.ALL)
    private List<CategoryEntity> subCategories;
}

When i create a category I use a model:

@Getter @Setter
public class CategoryRequestModel {
    private String name;
    private String parentCategoryKeyId;
}

In this model i want parentCategoryKeyId to match with the categoryKeyId of the parent.

For example if i create a "top" category :

{
  "name": "topCategory"
} 

It returns me :

{
    "categoryKeyId": "jUcpO27Ch2YrT2zkLr488Q435F8AKS",
    "name": "topCategory",
    "subCategories": null
}

When i do this :

{
  "name": "sub",
  "parentCategoryKeyId": "jUcpO27Ch2YrT2zkLr488Q435F8AKS"
} 

In my Controller, i pass the rest object to a DTO Layer which calls a service :

public CategoryRestResponseModel createCategory(@RequestBody CategoryRequestModel categoryRequestModel) {
    CategoryRestResponseModel returnValue = new CategoryRestResponseModel();
    if( categoryRequestModel.getName().isEmpty())
        throw new NullPointerException(ErrorMessages.MISSING_REQUIRED_FIELDS.getErrorMessage());
    ModelMapper modelMapper = new ModelMapper();
    CategoryDto categoryDto = modelMapper.map(categoryRequestModel, CategoryDto.class);
    CategoryDto createdCategory = categoryService.createCategory(categoryDto);
    returnValue = modelMapper.map(createdCategory, CategoryRestResponseModel.class);
    return returnValue;
}

My CategoryDto is a basic POJO :

@Getter @Setter
public class CategoryDto implements Serializable {
    @Getter(AccessLevel.NONE)
    private static final long serialVersionUID = 1L;

    private String categoryKeyId;
    private String parentCategoryKeyId;
    private String name;
    private CategoryDto parentCategory;
    private List<CategoryDto> subCategories;
}

In my Service :

   public CategoryDto createCategory(CategoryDto categoryDto) {
        //1. Create an empty object to return
        System.out.println("Hello World");
        CategoryDto returnValue = new CategoryDto();
        System.out.println("CategoryDto: " + categoryDto);
        // check if category exists
        if (categoryRepository.findByName(categoryDto.getName()) != null)
            throw new ApplicationServiceException("Record already in Database");

        ModelMapper modelMapper = new ModelMapper();
        CategoryEntity categoryEntity = modelMapper.map(categoryDto, CategoryEntity.class);

        // Generate categoryKeyId
        String categoryKeyId = utils.generateCategoryKeyId(30);
        categoryEntity.setCategoryKeyId(categoryKeyId);
        System.out.println("categoryDto parentCategory: " + categoryDto.getParentCategory());
        System.out.println("CategoryDto: " + categoryDto);

        if(categoryDto.getParentCategoryKeyId() != null) {
            CategoryEntity parentCategory = categoryRepository.findByCategoryKeyId(categoryDto.getParentCategoryKeyId());
            categoryEntity.setParentCategory(parentCategory);
            System.out.println("CategoryEntity: " + categoryEntity);
            System.out.println("parentCategory: " + parentCategory);
        }

        CategoryEntity storedCategory = categoryRepository.save(categoryEntity);
        returnValue = modelMapper.map(storedCategory, CategoryDto.class);

        return returnValue;
    }

My issue is that I would like to save the subcategory and retrieve the ID that match the categoryKeyId ...

In the database my entry should be like this

My First entry should have: id = 1 - parent_id = null, category_key_id = jUcpO27Ch2YrT2zkLr488Q435F8AKS, name = topCategory ... AND : id = 2 - parent_id = 1 , category_key_id = "another generated key", name= sub

Unfortunatelly I just persist the id, the categorykeyid and the name. I removed id from CategoryDto and i obtain : 1) Converter org.modelmapper.internal.converter.NumberConverter@348fc3d8 failed to convert java.lang.String to java.lang.Long.


Solution

  • I solved it in a "dirty" way. I just changed my object in entry and added a long id.

    It gives me :

    @Getter @Setter
    public class CategoryRequestModel {
        private Long id;
        private String name;
        private String parentCategoryKeyId;
    }