I have two entities
@Entity
@Table(name = "categories")
public class Category {
@Getter
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "category_id", unique = true, nullable = false)
private long categoryId;
@Getter @Setter
@ManyToMany(mappedBy = "categories", cascade = {
CascadeType.PERSIST,
CascadeType.MERGE
})
List<Product> products;
@Getter @Setter
@Column(name = "category_name", nullable = false, unique = true)
private String categoryName;
And
@Entity
@Table(name = "products")
public class Product {
@Getter
@Id @GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "product_id", unique = true, nullable = false)
private long productId;
@Getter @Setter
@Column(name = "price")
private float price;
@Getter @Setter
@ManyToMany(cascade = CascadeType.ALL)
@JoinTable(name = "categories_product")
private List<Category> categories;
@Getter @Setter
@Column(name = "product_code", unique = true, nullable = false)
private String productCode;
@Getter @Setter
@Column(name = "product_name", nullable = false)
private String productName;
@Getter @Setter
@Column(name = "description", nullable = false)
private String description;
@Getter @Setter
@Column(name = "short_description", nullable = false)
private String shortDescription;
}
I`m using MapStruct for DTO. When I want to add new product through controller I get the following error: org.hibernate.PropertyValueException: not-null property references a null or transient value: com.project.shop.models.Category.categoryName
As I understand, hibernate tries to create a new Category, when I want it to use an already existing one in database.
CategoryDTO:
@Getter
@Setter
public class CategoryDto {
private long categoryId;
private String categoryName;
private boolean categoryActive;
}
ProductDTO:
@Getter
@Setter
public class ProductDto {
private String productName;
private String productCode;
private float price;
private String shortDescription;
private String description;
private List<CategoryDto> categories;
}
CategoryMapper:
@Mapper(componentModel = "spring")
public interface CategoryMapper {
CategoryDto toDto(Category category);
List<CategoryDto> toDtos(List<Category> categories);
List<Category> toModels(List<CategoryDto> categoryDtos);
Category toModel(CategoryDto categoryDto);
}
ProductMapper:
@Mapper(uses = {CategoryMapper.class},
componentModel = "spring")
public interface ProductMapper {
ProductDto toDto(Product product);
List<ProductDto> toDtos(List<Product> products);
List<Product> toModels(List<ProductDto> productDtos);
Product toModel(ProductDto productDto);
}
Controller:
@PostMapping("/product")
public ResponseEntity<ProductDto> create(@RequestBody ProductDto productDto) {
productService.save(productMapper.toModel(productDto));
return ResponseEntity.status(HttpStatus.CREATED).body(productDto);
}
productService.save:
public void save(Product product) {
productRepository.save(product);
}
It is not that easy basically. My suggestion (and my implementation) is that you pass only the categoryId
with your ProductDTO
. And at the service, take this ID, find the respective Category via a Repository and then set the Product's Category to this entity. Simple example:
public ProductDTO addProduct(ProductDTO newDto) {
Category category = categoryRepo.findById(newDto.getCategory().getId())
.orElseThrow(// something);
Product entity = modelMapper.map(newDto, Product.class); // This does the same thing as your mapper, You can also implement this in your project
entity.setCategory(category );
return modelMapper.map(productRepo.save(entity), ProductDTO.class); // This saves the entity and converts it to a DTO and returns it
}
If you look at the identity, nullable = false option appears to be defined option is defined.
@Entity
@Table(name = "categories")
public class Category {
....
@Getter @Setter
@Column(name = "category_name", nullable = false, unique = true)
private String categoryName;
I think it would be good to look for the categoryName column value of CategoryDto first.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.