ModelMapper создает проблемы для преобразования объектов DTO в Entity - PullRequest
0 голосов
/ 28 марта 2020

У меня есть простое приложение с пружинной загрузкой, в котором необходимо сохранить Product и выполнить преобразование между DTO и Entity. Я использую зависимость ModelMapper. Пользователь может прикрепить ProductCategory к Product или оставить его пустым. Точно так же Product может иметь несколько ReplaceNumber или быть пустым. Если я не присоединяю категорию, это дает ошибку. Если я добавляю категорию, это сохраняет продукт с прикрепленной категорией. Если я оставлю массив replaceNumbers пустым, он сохранится. Если я его заполняю, это дает ошибки. Ошибки описаны ниже.

Категория продукта

@Entity
@Table(name = "product_categories")
public class ProductCategory
{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotBlank
    @Column(name = "name", nullable = false)
    @Size(max = 20)
    private String name;

    public ProductCategory()
    {

    }

    public ProductCategory(String name)
    {
        this.name = name;
    }
}

ReplaceNumber

@Entity
@Table(name = "replace_numbers")
public class ReplaceNumber
{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotBlank
    @Size(max = 20)
    private String partNumber;

    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "product_id", nullable = false)
    private Product product;

    public ReplaceNumber()
    {

    }

    public ReplaceNumber(String partNumber)
    {
        this.partNumber = partNumber;
    }
}

Product

@Entity
@Table(name = "products", indexes = {@Index(name= "part_number_index", columnList = "part_number", unique = true)})
public class Product
{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotBlank
    @Column(name = "part_number", nullable = false)
    @Size(max = 20)
    private String partNumber;

    @NotBlank
    @Size(max = 255)
    private String description;

    @OneToMany(
            mappedBy = "product",
            cascade = CascadeType.ALL,
            fetch = FetchType.EAGER,
            orphanRemoval = true
    )
    @Fetch(FetchMode.SELECT)
    private List<ReplaceNumber> replaceNumbers = new ArrayList<>();

    @ManyToOne
    @JoinColumn(name = "product_category_id", referencedColumnName = "id")
    private ProductCategory category;
}

Ниже приведены классы DTO, которые необходимо преобразовать.

ReplaceNumberRequest

public class ReplaceNumberRequest
{
    @NotBlank
    @Size(max = 20)
    private String partNumber;

    public String getPartNumber()
    {
        return partNumber;
    }

    public void setPartNumber(String partNumber)
    {
        this.partNumber = partNumber;
    }
}

ProductCategoryResponse

public class ProductCategoryResponse
{
    private Long id;
    private String name;

    public ProductCategoryResponse()
    {

    }

    public ProductCategoryResponse(String name)
    {
        this.name = name;
    }
}

ProductRequest

public class ProductRequest
{
    @NotBlank
    @Size(max = 20)
    private String partNumber;

    @NotBlank
    @Size(max = 255)
    private String description;

    private List<ReplaceNumberRequest> replaceNumbers = new ArrayList<>();

    private ProductCategoryResponse category;
}

ProductService

@Service
public class ProductService
{
    @Autowired
    ProductRepository productRepository;

    public Product create(ProductRequest productRequest)
    {
        Product product = new Product();

        org.modelmapper.ModelMapper modelMapper = new org.modelmapper.ModelMapper();
        modelMapper.map(productRequest, product);

        return productRepository.save(product);
    }
}

Если я отправлю следующее JSON от Postman

{
  "partNumber": "443455783",
  "description": "443434",
  "replaceNumbers": [],
  "category": ""
}

Это идет для сохранения пустой категории и выдает следующую ошибку:

org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : org.walana.GP.model.Product.category -> org.walana.GP.model.ProductCategory; nested exception is java.lang.IllegalStateException: org.hibernate.TransientPropertyValueException: object references an unsaved transient instance - save the transient instance before flushing : org.walana.GP.model.Product.category -> org.walana.GP.model.ProductCategory

Если я отправлю следующее JSON из Postman

{
  "partNumber": "443455783",
  "description": "443434",
  "replaceNumbers": [
    {
        "partNumber": "123455"
    },
    {
        "partNumber": "343435"
    }
    ],
  "category": {
    "id": 1,
    "name": "Mounting"
  }
}

выдает следующую ошибку.

could not execute statement; SQL [n/a]; constraint [part_number_index]; nested exception is org.hibernate.exception.ConstraintViolationException: could not execute statement
...