Как настроить объекты списка для моделирования в форме (тег <form:input>)

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

Сущности: Меню, Блюдо

@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: Неверное свойство 'тарелки[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-СТРАНИЦА

      <!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 вызывает это поле таким образом. Спасибо за вашу помощь!

Не могли бы вы поделиться всем своим кодом и полной трассировкой стека?

akortex 17.03.2019 17:28

@Aris_Kortex, я поделился кодом для сущностей и jsp. Насчет stacktrace: исключений нет.

Anthony 17.03.2019 17:39

Возможный дубликат Как сохранить много объектов в пружине <form:form>

akortex 17.03.2019 17:40

@Aris_Kortex Здесь та же проблема, но ответа нет

Anthony 17.03.2019 17:43
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
1
4
58
0

Другие вопросы по теме