Как установить объекты списка для моделирования по форме (тег) - PullRequest
1 голос
/ 17 марта 2019

У меня есть веб-приложение. Фрагмент кода ниже.

Объекты: Меню, Блюдо

@Entity
@Table(name = "menus")
public class Menu {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name = "id")
    private int id;

    @Column(name = "name")
    private String name;

    @Column(name = "date")
    private LocalDateTime date;

    @Column(name = "total_cost")
    private double cost;

    @ManyToOne(cascade = {
            CascadeType.DETACH, CascadeType.MERGE,
            CascadeType.PERSIST, CascadeType.REFRESH})
    @JoinColumn(name = "restaurant_id")
    private Restaurant restaurant;

    @OneToMany(fetch = FetchType.LAZY, mappedBy = "menu", cascade = CascadeType.ALL)
    private Set<Dish> dishes = new HashSet<>();

    @OneToMany(fetch = FetchType.EAGER, mappedBy = "menu", cascade = CascadeType.ALL)
    private Set<Vote> votes;

    public Menu() {
    }

    public Menu(String name, LocalDateTime date, double cost, Restaurant restaurant) {
        this.name = name;
        this.date = date;
        this.cost = cost;
        this.restaurant = restaurant;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public Restaurant getRestaurant() {
        return restaurant;
    }

    public void setRestaurant(Restaurant restaurant) {
        this.restaurant = restaurant;
    }

    public Set<Dish> getDishes() {
        return dishes;
    }

    public List<Dish> getDishesAsList(){
        return new ArrayList<>(dishes);
    }

    public void setDishes(Set<Dish> dishes) {
        this.dishes = dishes;
    }

    public Set<Vote> getVotes() {
        return votes;
    }

    public void setVotes(Set<Vote> votes) {
        this.votes = votes;
    }

    public LocalDateTime getDate() {
        return date;
    }

    public void setDate(LocalDateTime date) {
        this.date = date;
    }

    public double getCost() {
        return cost;
    }

    public void setCost(double cast) {
        this.cost = cast;
    }

    public int getVoteCount() {
        return votes.size();
    }

    @Override
    public String toString() {
        return "Menu{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", date=" + date +
                ", cast=" + cost +
                ", restaurant=" + restaurant +
                ", dishes=" + dishes +
                ", votes=" + votes +
                '}';
    }
}

Метод getDishesAsList (просто обернуть на Набор блюд) был создан, чтобы избежать этого исключения: org.springframework.beans.InvalidPropertyException: недопустимое свойство 'dish [0]' класса бобов [ru. icoltd.rvs.entity.Menu]: не удается получить элемент с индексом 0 из набора размером 0

=============================================== ===========================

  @Entity
  @Table(name = "dishes")
  public class Dish {

  @Id
  @GeneratedValue(strategy = GenerationType.IDENTITY)
  @Column(name = "id")
  private int id;

  @Column(name = "description")
  private String description;

  @Column(name = "price")
  private double price;

  @ManyToOne(cascade = {
          CascadeType.DETACH, CascadeType.MERGE,
          CascadeType.PERSIST, CascadeType.REFRESH
  })
  @JoinColumn(name = "menu_id")
  private Menu menu;

  public Dish() {
  }

  public Dish(String description, double price, Menu menu) {
      this.description = description;
      this.price = price;
      this.menu = menu;
  }

  public int getId() {
      return id;
  }

  public void setId(int id) {
      this.id = id;
  }

  public String getDescription() {
      return description;
  }

  public void setDescription(String description) {
      this.description = description;
  }

  public double getPrice() {
      return price;
  }

  public void setPrice(double price) {
      this.price = price;
  }

  public Menu getMenu() {
      return menu;
  }

  public void setMenu(Menu menu) {
      this.menu = menu;
  }

  @Override
  public String toString() {
      return "Dish{" +
              "id=" + id +
              ", description='" + description + '\'' +
              ", price=" + price +
              ", menu=" + menu +
              '}';
  }
}

=============================================== ===========================

Контроллер

@Controller
@RequestMapping("/menu")
public class MenuController {

private MenuService menuService;

    @Autowired
    public void setMenuService(MenuService menuService) {
        this.menuService = menuService;
    }

    @PostMapping("/save")
    public String addMenu(@ModelAttribute("menu") Menu menu) {
        //menu.getDishes(); always empty
        menuService.saveMenu(menu);
        return "redirect:/someUrl";
    }

    @GetMapping("/update")
    public String updateMenu(@RequestParam("menuId") int menuId, Model model) {
        Menu menu = menuService.getMenu(menuId);
        model.addAttribute("menu", menu);
        model.addAttribute("restaurantId", menu.getRestaurant().getId());
        return "menu-form";
    }

=============================================== =========================== JSP PAGE

      <!doctype html>
   <%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
   <%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
   <%@taglib uri="http://www.springframework.org/tags" prefix="spring" %>
   <html>

<head>
   <title>
       Add Menu
   </title>
</head>

<body>

<h3>Add Menu</h3>
<hr>

<c:url var="save" value="/menu/save">
   <c:param name="restId" value="${restaurantId}"/>
</c:url>

<form:form action="${save}" method="post" modelAttribute="menu">

   <form:hidden path="id"/>
   <table>
       <tbody>
       <tr>
           <td>Name:</td>
           <td><form:input path="name"/></td>
       </tr>

       <tr>
           <td>Date:</td>
           <td><form:input type="date" path="date"/></td>
       </tr>

       <tr>
           <td><h4>List dishes:</h4></td>
       </tr>

       <c:forEach items="${menu.dishesAsList}" varStatus="status" var="dish">

           <c:url var="deleteLink" value="/dish/delete">
               <c:param name="menuId" value="${menu.id}"/>
               <c:param name="dishId" value="${dish.id}"/>
           </c:url>

           <form:hidden path="dishes[${status.index}].id" value="${dish.id}"/>
           <tr>
               <td>Dish #${status.index}</td>
               <td><form:input path="dishes[${status.index}].description" value="${dish.description}"/></td>
               <td><a href="${deleteLink}">Delete</a></td>
           </tr>
       </c:forEach>

       <c:url var="showFormLink" value="/dish/showFormForAdd">
           <c:param name="menuId" value="${menu.id}"/>
       </c:url>
       <tr>
           <td></td>
           <td><a href="${showFormLink}">Add new dish</a></td>
       </tr>

       <tr>
           <td><input type="submit" value="Save" class="save"/></td>
       </tr>

       </tbody>
   </table>

</form:form>

<hr>
<p>Total cost: </p>

<p><a href="${pageContext.request.contextPath}/restaurant/${restaurantId}/menus">Back to restaurant list</a></p>

</body>
</html>

=============================================== ===========================

Вопрос : Я хочу обновить или добавить Меню вместе с Список блюд в форме. Как установить коллекцию Блюдо для сущности Меню по всей форме напрямую? Когда я пытаюсь отправить форму, поле блюда всегда пусто. Я не могу понять, какой установщик класса Menu вызывает это поле таким образом. Спасибо за вашу помощь!

...