Метод covertValue для объекта Spring не конвертирует некоторые поля - PullRequest
1 голос
/ 04 марта 2020

У меня есть приложение Spring Boot 2, которое использует метод ObjectMapper.convertValue для преобразования из / в сущности и DTO.

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

Сущность продукта:

@Entity
@Table(name = "product")
@Getter
@Setter
@NoArgsConstructor(access = AccessLevel.PUBLIC)
@AllArgsConstructor
public class Product extends AbstractPersistable<Long> {

    @Column
    private String name;

    @Column
    private String description;

    @Column
    private BigDecimal price;

    @Column
    private int weight;

    @Column
    private int stock = 0;

    @Column(name = "image_url", length = 254, unique = true)
    private String imageUrl;

    @NotEmpty
    @Column(name = "banner_image_url", length = 254, unique = true)
    private String bannerImageUrl;

    @ManyToOne(optional = false, fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @JoinColumn(name = "product_category_id")
    @JsonBackReference
    private Category category;

    @OneToMany(mappedBy = "product", fetch = FetchType.EAGER, cascade = CascadeType.ALL)
    @OrderBy
    @JsonManagedReference
    private SortedSet<ProductThumbnail> thumbnails;

    public Product(Long id) {
        this.setId(id);
    }

    public Product(String name, String description, BigDecimal price, int weight) {
        this.name = name;
        this.description = description;
        this.price = price;
        this.weight = weight;
    }
}

DTO продукта:

@Getter
@Setter
@NoArgsConstructor
public class ProductDTO {

    private Long id;

    private String name;

    private String description;

    private BigDecimal price;

    private int weight;

    private String imageUrl;

    private String bannerImageUrl;

    private CategoryDTO category;

    private SortedSet<ProductThumbnailDTO> thumbnails;

    public ProductDTO(@JsonProperty("id") Long id) {
        this.id = id;
    }

    @JsonCreator
    public ProductDTO(@JsonProperty("id") Long id,
                      @JsonProperty("name") String name,
                      @JsonProperty("description") String description,
                      @JsonProperty("price") BigDecimal price,
                      @JsonProperty("weight") int weight,
                      @JsonProperty("imageUrl") String imageUrl,
                      @JsonProperty("category") CategoryDTO category,
                      @JsonProperty("variants") Set<ProductVariantDTO> variants) {
        this.id = id;
        this.name = name;
        this.description = description;
        this.price = price;
        this.weight = weight;
        this.imageUrl = imageUrl;
        this.category = category;
        this.variants = variants;
    }
}

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

ProductDTO productDTO = objectMapper.convertValue (product, ProductDTO.class);

, за исключением category. Таким образом, категория в переменной product установлена, а результирующее поле productDTO.category после преобразования становится пустым.

Сущность категории:

@Entity
@Table(name = "product_category")
@Getter
@Setter
@NoArgsConstructor(access = AccessLevel.PUBLIC)
@AllArgsConstructor
@Immutable
public class Category extends AbstractPersistable<Long> {

    @Column
    private String name;

    @Column
    private String description;

    @OneToMany(mappedBy = "category", cascade = CascadeType.ALL, fetch = FetchType.LAZY)
    @JsonManagedReference
    private Set<Product> products = new HashSet<>();
}

Категория DTO:

@Data
@NoArgsConstructor
public class CategoryDTO {

    private String name;

    private String description;

    @JsonIgnore
    private Set<Product> products = new HashSet<>();

    @JsonCreator
    public CategoryDTO(@JsonProperty("name") String name, @JsonProperty("description") String description) {
        this.name = name;
        this.description = description;
    }
}

Итак, вопрос в том, почему ObjectMapper не может автоматически преобразовать поле категории? Есть ли какое-либо условие, которое мешает этому случиться? Потому что не выдается никакой ошибки.

Ниже приведен компонент EJB:

@Bean
public ObjectMapper objectMapper() {
    ObjectMapper objectMapper = new ObjectMapper();
    objectMapper.enable(MapperFeature.ACCEPT_CASE_INSENSITIVE_ENUMS);
    objectMapper.disable(SerializationFeature.FAIL_ON_EMPTY_BEANS);
    objectMapper.setSerializationInclusion(JsonInclude.Include.NON_NULL);
    objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
    objectMapper.findAndRegisterModules();
    objectMapper.registerModules(module(), new Jdk8Module());
    return objectMapper;
}

Джексон Деп версия 2.10.1

Спасибо

1 Ответ

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

Итак, главный виновник в вашем коде - @JsonBackReference. Как @JsonBackReference аннотация присваивается

    @JsonBackReference
    private Category category;

Эта категория автоматически удаляется при сериализации. С эта ссылка:

@ JsonManagedReference является передней частью ссылки - той, которая сериализуется нормально. @JsonBackReference - задняя часть ссылки - она ​​будет исключена из сериализации.

Поэтому вместо @JsonBackReference попробуйте использовать: @JsonManagedReference.

Надеюсь, что это решит вашу проблему.

...