As context, I create a Spring Boot REST API and I encountered the next problem, when I map a Entity class to a DTO, it won't take one of the fields, more precisely the department field.
Here foundItem = mapper.convertToType(itemDTO, Item.class);
after this mapping from a itemDTO, foundItem won't contain a department, it will be just null instead
public ItemDTO updateItem(Long departmentId, Long itemId, ItemDTO itemDTO) throws ApiException {
Department department = departmentRepository.findById(departmentId).orElseThrow(
() -> new ApiException("Department with this id does not exist ",
HttpStatus.NOT_FOUND));
Item foundItem = validateItem(itemId);
Item convertedItem = mapper.convertToType(itemDTO, Item.class);
if (convertedItem.getStock() < 0) {
throw new ApiException("Stock must be a positive value", HttpStatus.BAD_REQUEST);
}
if (convertedItem.getStockThreshold() < 0) {
throw new ApiException("Stock threshold must be a positive value", HttpStatus.BAD_REQUEST);
}
itemDTO.setId(itemId);
itemDTO.setDepartment(mapper.convertToType(department, DepartmentDTO.class));
foundItem = mapper.convertToType(itemDTO, Item.class);
itemRepository.save(foundItem);
// ItemDTO returnItem = mapper.convertToType(convertedItem, ItemDTO.class);
logger.info("Updated item");
return itemDTO;
}
EDIT!
This is my Mapper class
@Component
public class Mapper {
private final ModelMapper modelMapper;
private final Logger logger = LoggerFactory.getLogger(ModelMapper.class);
public Mapper(ModelMapper modelMapper) {
this.modelMapper = modelMapper;
}
public <T> T convertToType(Object source, Class<T> resultClass) {
logger.debug("converted object from " source.getClass().getSimpleName() " to " resultClass.getSimpleName());
return modelMapper.map(source, resultClass);
}
}
ItemDTO class
@AllArgsConstructor
@NoArgsConstructor
@Setter
public class ItemDTO {
private Long id;
private String description;
private String price;
private int stock;
private int stockThreshold;
private DepartmentDTO department;
public Long getId() {
return id;
}
public String getDescription() {
return description;
}
public String getPrice() {
return price;
}
public int getStock() {
return stock;
}
public int getStockThreshold() {
return stockThreshold;
}
public Long getDepartment() {
return department.getId();
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
ItemDTO itemDTO = (ItemDTO) o;
return stock == itemDTO.stock && stockThreshold == itemDTO.stockThreshold &&
id.equals(itemDTO.id) && description.equals(itemDTO.description) &&
price.equals(itemDTO.price) && department.equals(itemDTO.department);
}
@Override
public int hashCode() {
return Objects.hash(id, description, price, stock);
}
And Item class
@AllArgsConstructor
@NoArgsConstructor
@Getter
@Setter
@Entity
@Table(name = "ITEMS")
public class Item {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id", unique = true, nullable = false)
private Long id;
private String description;
private String price;
private int stock;
private int stockThreshold = 5;
@ManyToOne(fetch = FetchType.LAZY, optional = false)
@JoinColumn(name = "department_id", nullable = false)
@OnDelete(action = OnDeleteAction.CASCADE)
@JsonIgnore
private Department department;
@Override
public String toString() {
return "Item{"
"id=" id
", description='" description '\''
", price='" price '\''
", stock=" stock
", department=" department
'}';
}
}
DepartmentDTO Class:
@NoArgsConstructor
@Getter
@Setter
public class DepartmentDTO {
private Long id;
private String description;
private List<Item> items;
public DepartmentDTO(long id, String description) {
this.id = id;
this.description = description;
}
@Override
public String toString() {
return "DepartmentDTO{"
"id=" id
", description='" description '\''
", items=" items
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
DepartmentDTO that = (DepartmentDTO) o;
return Objects.equals(id, that.id) && Objects.equals(description, that.description) && Objects.equals(items, that.items);
}
// @Override
// public int hashCode() {
// return Objects.hash(id, description, items);
// }
}
Department Class
@NoArgsConstructor
@Entity
@Getter
@Setter
@Table(name = "DEPARTMENTS")
public class Department {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Long id;
private String description;
@OneToMany(mappedBy = "department", fetch = FetchType.EAGER,
cascade = CascadeType.ALL)
private List<Item> items;
public Department(Long id, String description) {
this.id = id;
this.description = description;
}
@Override
public String toString() {
return "Department{"
"id=" id
", description='" description '\''
", items=" items
'}';
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (!(o instanceof Department)) return false;
Department that = (Department) o;
return id.equals(that.id) && Objects.equals(description, that.description) && Objects.equals(items, that.items);
}
@Override
public int hashCode() {
return Objects.hash(id, description, items);
}
}
A minimal reproducible example:
Department department = new Department(1L, "first");
ItemDTO itemDTO = new ItemDTO(1L, "modified description for update",
"200$", 200, 6, mapper.convertToType(department,
DepartmentDTO.class));
Item item = mapper.convertToType(itemDTO,Item.class);
item will have it's department field null, because my mapper has a problem in mapping the deparment.
CodePudding user response:
Preface: Thank you for quickly responding to my comments. I see that you are fairly new to Stack Overflow and looking back at your questions, I have noticed a trend. I suggest you read How do I ask a good question? and Minimal, Reproducible Example.
Answer:
TLDR: You have to make ItemDTO#getDepartment
return the department
object.
Here's how I approached the problem:
- Created a new project to hold and run your code.
- Cleaned up your code.
- Removed JPA annotations.
- Removed Jackson annotations.
- Removed Lombok annotations.
- The only dependency I could not resolve was
ModelMapper
. I assumed that this is from ModelMapper. I have never used it before, but I made the assumption that it uses getters/setters like popular serialization libraries such as Jackson do. - This led me to check your getters/setters, wherein I found that
ItemDTO#getDepartment
returned the ID of the department, not theDepartmentDTO
object itself.
I thought I would share how I tackled your problem with the hope that it will help you better solve problems yourself!