I have a DTO that has a Collection of another DTO. I want to use Spring data JPA projections to fetch only the data needed for this particular DTO. But I don't know how.
Upd: added Entity classes. The question is about Spring Data Projections, not Spring data jpa in general.
@Getter
@Setter
@NoArgsConstructor
public class RestaurantDto {
private int id;
private String name;
private String address;
private int votes;
private List<DishDtoShort> dishes;
public RestaurantDto(String name, String address) {
this.name = name;
this.address = address;
}
public RestaurantDto(int id, String name, String address,int votes, List<DishDtoShort> dishes) {
this.votes = votes;
this.id = id;
this.name = name;
this.address = address;
this.dishes = dishes;
}
public void addDish(DishDtoShort dishDtoShort) {
dishes.add(dishDtoShort);
}
public List getDishes() {
return Collections.unmodifiableList(dishes);
}
}
DTO inside a Collection
@Getter
@Setter
@NoArgsConstructor
public class DishDtoShort {
private int id;
private String name;
private double price;
public DishDtoShort(int id, String name, double price) {
this.id = id;
this.name = name;
this.price = price;
}
}
Restaurant Entity
@Entity
@Getter
@Setter
@NoArgsConstructor
@ToString(exclude = {"votes", "dishes"})
public class Restaurant extends AbstractNamedEntity {
String address;
@OneToMany(mappedBy = "restaurant", cascade = CascadeType.ALL, orphanRemoval = true)
@JsonManagedReference
private List<Dish> dishes;
@OneToMany(mappedBy = "restaurant", cascade = CascadeType.ALL, orphanRemoval = true)
@JsonManagedReference
private List<Vote> votes;
public void addDish(Dish dish) {
this.dishes.add(dish);
dish.setRestaurant(this);
}
public void removeDish(Dish dish) {
this.dishes.remove(dish);
dish.setRestaurant(null);
}
public void addVote(Vote vote) {
this.votes.add(vote);
vote.setRestaurant(this);
}
public void removeVote(Vote vote) {
this.votes.remove(vote);
vote.setRestaurant(null);
}
public Restaurant(String name, String address) {
super(name);
this.address = address;
}
public List<Dish> getDishes() {
return Collections.unmodifiableList(dishes);
}
public List<Vote> getVotes() {
return Collections.unmodifiableList(votes);
}
}
Dish Entity
@Entity
@Getter
@Setter
@ToString
@NoArgsConstructor
public class Dish extends AbstractNamedEntity {
private double price;
private LocalDate dateAdded;
@ManyToOne(fetch = FetchType.LAZY)
@JsonBackReference
private Restaurant restaurant;
public void setRestaurant (Restaurant restaurant) {
this.restaurant = restaurant;
}
public Dish(String name, double price, Restaurant restaurant) {
super(name);
this.price = price;
this.dateAdded = LocalDate.now();
this.restaurant = restaurant;
}
}
P.S. I know about wrong class naming.
I think, you just have to define your DTO in your repository and don't forget to have same name on your entity and DTO for the mapping :
@Repository
public interface RestaurantRepository extends JpaRepository<Restaurant, Integer> {
List<RestaurantDto> findByName(String name);
}
you can have more informations here : https://www.baeldung.com/spring-data-jpa-projections