У меня есть простое приложение с пружинной загрузкой, в котором необходимо сохранить 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