Spring MVC Приложение в форме: input path = преобразует данный объект в строку, когда мне нужен объект для доступа к значению карты - PullRequest
0 голосов
/ 26 января 2020

В моем приложении Spring MVC я пытаюсь создать небольшую форму, которая обновляет параметр object (Quantity), то есть значение на карте, которое keys равно objects (Case).

Я получаю эту ошибку:

org.springframework.beans.InvalidPropertyException: случаи недопустимых свойств [Case o wymiarach: 300x200x100mm i powierzchni 0.22m2, тип = KUFER, материал = SKLEJKA , kolor = BLACK, wypelnienie = FOAM, uchwyty = KASETOWY, iloscUchwytow = 0, kola = false, iloscKol = 0, zamki = MOTYLKOWE, uwagi =, cena = 110.0zł] 'класса бобов [com.wojity.wmcase. Порядок]: недопустимый индекс в случаях пути свойств [Case w wymiarach: 300x200x100 мм и Powierzchni 0,22 м2, тип = KUFER, материал = SKLEJKA, цвет = ЧЕРНЫЙ, wypelnienie = ПЕНА, uchwyty = KASETOWY, iloscUchwytow = 0, ilos kola = 0, kola = = 0, zamki = MOTYLKOWE, uwagi =, cena = 110.0zł] '; вложенным исключением является org.springframework.beans.ConversionNotSupportedException: не удалось преобразовать значение свойства типа 'java .lang.String' в требуемый тип 'com.wojto.wmcase.entity.Case' для свойства 'null'; вложенное исключение: java .lang.IllegalStateException: невозможно преобразовать значение типа 'java .lang.String' в требуемый тип 'com.wojto.wmcase.entity.Case': не найдено подходящих редакторов или стратегии преобразования

Фрагмент кода выглядит следующим образом:

<form:form action="updateQuantity" modelAttribute="order" method="PUT">
   <form:input class="" path="cases[${tempCase}].quantity" 
        value="${order.getCases().get(tempCase).getQuantity()}"/>
                                |
        <button type="submit" class="btn btn-link my-3" >Zapisz ilość</button>
 </form:form></td>

tempCase создается следующим образом:

<c:forEach var="tempCase" items="${order.getCaseList()}">

Итак, что здесь происходит является то, что путь получает правильный объект (параметры, как и ожидалось), но по какой-то причине преобразовывает в строку с помощью метода toString(), после чего он жалуется, что не может преобразовать его обратно из String в Case ...

Я также пробовал: cases['${tempCase}'], cases['tempcase'] и cases[tempCase]. Он всегда преобразует его в строку, в последних двух он принимает буквально строку «tempCase».

Сущности:

@Entity
@Proxy(lazy=false)  // test
@Table(name="orders")
public class Order {

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

    @OneToMany(fetch=FetchType.LAZY, cascade=CascadeType.ALL)
    @JoinTable(name="case_quantities",
        joinColumns = {@JoinColumn(name="order_id", referencedColumnName="id")},
        inverseJoinColumns = {@JoinColumn(name="quantity_id", 
        referencedColumnName="id")}
        )
    @MapKeyJoinColumn(name="case_id")
    private Map<Case, Quantity> cases;

    @Column(name="comments")
    private String comments;
    @Column(name="charge")
    private double charge;
    @Enumerated(EnumType.STRING)
    private OrderStatus orderStatus;
    @Column(name="dt")
    private Date date;

    @ManyToOne(cascade= {CascadeType.PERSIST, CascadeType.MERGE,
                         CascadeType.DETACH, CascadeType.REFRESH})
    @JoinColumn(name="client_id")
    private Client client;
(...)
    public Map<Case, Quantity> getCases() {
        if(cases == null) {
            this.cases = new HashMap<Case, Quantity>();
        }
        return cases;
    }

    public List<Case> getCaseList(){
        if(cases == null) {
            this.cases = new HashMap<Case, Quantity>();
        }
        return new ArrayList<>(cases.keySet());
    }
(...)

@Entity
@Proxy(lazy=false)
@Table(name="cases")
public class Case {

    @Id
    @GeneratedValue(strategy=GenerationType.IDENTITY)
    @Column(name="id")
    private int id;
    @Column(name="length")
    private int length;
    @Column(name="width")
    private int width;
    @Column(name="height")
    private int height;
    @Column(name="surface")
    private double surface;

    @Enumerated(EnumType.STRING)
    private Type type;
    @Enumerated(EnumType.STRING)
    private Material material;
    @Enumerated(EnumType.STRING)
    private Color color;
    @Enumerated(EnumType.STRING)
    private Filling filling;

    @Enumerated(EnumType.STRING)
    private Handle handle;
    @Column(name="handle_num")
    private int handleNum;

    @Column(name="wheels")
    private boolean wheels;
    @Column(name="wheel_num")
    private int wheelNum;

    @Enumerated(EnumType.STRING)
    private Locks locks;

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

    // Testing a bi-directional relationship
    @ManyToOne(cascade= {CascadeType.PERSIST, CascadeType.MERGE,
                        CascadeType.DETACH, CascadeType.REFRESH})
    @JoinColumn(name="order_id")
    private Order order;
(...)

Метод контроллера

    @PutMapping("/updateQuantity")
    public String updateQuantity(@RequestParam("quantity") int quantity,
                                 @ModelAttribute("tempCase") Case tempCase,
                                 @ModelAttribute("order") Order theOrder,
                                 Model theModel) {

        theOrder.getCases().get(tempCase).setQuantity(quantity);

        theModel.addAttribute(theOrder);

        return "redirect:/continueOrder";
    }

Всего jsp:

<%@ taglib uri="http://java.sun.com/jsp/jstl/core" prefix="c" %>
<%@ taglib prefix="form" uri="http://www.springframework.org/tags/form" %>
<!-- The below enabled Polish character rendering -->
<%@page pageEncoding="UTF-8" contentType="text/html; charset=UTF-8"%>

<!DOCTYPE html>

<html lang="pl">

<head>
    <title>WMCASE - </title>
    <meta charset="UTF-8">

    <!--
    <link href="<c:url value="/resources/css/style.css" />" rel="stylesheet">
    -->
    <link rel="stylesheet"
          href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css"
          integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T"
          crossorigin="anonymous">

</head>

<body>
<c:set var="now" value="<%=new java.util.Date()%>" />

    <div class="container-fluid bg-dark m-0">
        <h2 class="text-light text-center p-3">WMCase - Prośba o wycenę</h2>
    </div>


    <div class="container-fluid align-center">

        <form:form action="newCaseInOrder" method="GET">
            <input name="order" type="hidden" value="${order}"/>
            <input type="submit" value="Dodaj Skrzynkę" class="btn btn-dark my-3" />
        </form:form>

        <table class="table">
            <thead class="thead-dark">
                <tr>
                    <th scope="col" colspan="10">Skrzynki</th>
                </tr>
                <tr>
                    <th scope="col">Wymiary</th>
                    <th scope="col">Typ</th>
                    <th scope="col">Materiał</th>
                    <th scope="col">Kolor</th>
                    <th scope="col">Wypełnienie</th>
                    <th scope="col">Rączki</th>
                    <th scope="col">Koła</th>
                    <th scope="col">Zamki</th>
                    <th scope="col">Uwagi</th>
                    <th scope="col">Ilość</th>
                    <th scope="col">Akcja</th>
                </tr>

            <c:forEach var="tempCase" items="${order.getCaseList()}">

            <!-- Update case, quantity and delete Links -->
            <c:url var="updateQuantityLink" value="/updateQuantity">
                <c:param name="tempCase" value="${tempCase}"/>
                <c:param name="order" value="${order}"/>
            </c:url>

            <c:url var="updateLink" value="/updateCase">
                <c:param name="caseId" value="${tempCase.id}"/>
                <c:param name="orderId" value="${order}" />
            </c:url>

            <c:url var="deleteLink" value="/deleteCase">
                <c:param name="caseId" value="${tempCase.id}"/>
                <c:param name="orderId" value="${order}" />
            </c:url> 

                <tbody>
                    <tr>
                        <td> ${tempCase.length} x ${tempCase.width} x ${tempCase.height} mm</td>
                        <td> ${tempCase.type.getType()}</td>
                        <td> ${tempCase.material.getMaterial()}</td>
                        <td> ${tempCase.color.getColor()}</td>
                        <td> ${tempCase.filling.getFilling()}</td>
                        <td> ${tempCase.handle.getHandle()} - ${tempCase.getHandleNum() } </td>
                        <td> ${tempCase.getWheels()} - ${tempCase.getWheelNum()}</td>
                        <td> ${tempCase.locks.getLocks()} </td>
                        <td> ${tempCase.comments}</td>
                        <td>
                            <form:form action="updateQuantity" modelAttribute="order" method="PUT">

                                <form:input class=""
                                            path="cases[${tempCase}].quantity"
                                            value="${order.getCases().get(tempCase).getQuantity()}"/>
                                |
                                <button type="submit" class="btn btn-link my-3" >Zapisz ilość</button>
                            </form:form></td>
                        <td>
                            <a href="${updateLink}">Modyfikuj</a>
                             |
                            <a href="${deleteLink}"
                            onclick="if (!(confirm('Czy na pewno chcesz usunąć skrzynkę?'))) return false">
                            Usuń</a>
                        <td>
                    </tr>
                </tbody>
            <%-- </c:forEach> --%>
            </c:forEach>

        </table>
        <hr>


        <h3 class="">Dane kontaktowe:</h3>
        <form:form action="sendOrder" modelAttribute="order" method="POST">
            <form:hidden path="id"/>

            <div class="form-inline">
                <div class="col-auto form-group row">
                    <label class="col-form-label">Imię:</label>
                    <form:input class="form-control mx-3 text-right" type="text" path="client.name" />
                </div>
                <div class="col-auto form-group row">
                    <label class="col-form-label">Nazwisko:</label>
                    <form:input class="form-control mx-3 text-right" type="text" path="client.surname" />
                </div>
                <div class="col-auto form-group row">
                    <label class="col-form-label">Email:</label>
                    <form:input class="form-control mx-3 text-right" type="text" path="client.email" />
                </div>
                <div class="col-auto form-group row">
                    <label class="col-form-label">Telefon:</label>
                    <form:input class="form-control ml-3 text-right" type="text" path="client.tel" />
                </div>
            </div>
            <div>
                <label class="col-form-label">Komentarz:</label>
                <form:textarea rows="4" cols="30" class="form-control" type="text" path="comments" />
            </div>

            <button type="submit" class="btn btn-dark my-3" >Wyślij zapytanie</button>

         </form:form>

        <a href="${pageContext.request.contextPath}/clientOrders?clientId=${clientId}">Wróć do zamówień</a>

    </div>

    <script src="https://code.jquery.com/jquery-3.3.1.slim.min.js" integrity="sha384-q8i/X+965DzO0rT7abK41JStQIAqVgRVzpbzo5smXKp4YfRvH+8abtTE1Pi6jizo" crossorigin="anonymous"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script>
    <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script>

</body>
</html>

visual

1 Ответ

1 голос
/ 02 февраля 2020

Хорошо, я понял это. Проблема заключалась в том, что в forEach атрибут var преобразуется в строку, а не обратно в случай, когда я пытаюсь получить доступ к значению на карте вместе с ним. Поэтому я стараюсь ориентировать отредактированный параметр непосредственно на количество, удерживаемое заказом, я сохраняю новое количество во временном объекте количества, который находится в модели, а затем использую его для обновления объекта реального количества на карте, хранящейся в Порядок.

jsp

(...)
            <c:forEach var="tempCase" items="${order.getCases()}">
(...)
                            <form:form action="updateQuantity" modelAttribute="tempQuantity" method="PUT">
                                <input name="tempCase" type="hidden" value="${tempCase.key}"/>
                                <form:input class=""
                                            path="quantity"
                                            value="${tempCase.value.quantity}"
                                            />
                                <button type="submit" class="btn btn-link my-3" > Zapisz ilość</button>
                            </form:form></td>
(...)

Контроллер

(...)
    @PostMapping("/addCaseToOrder")
    public String addCaseToOrder(@ModelAttribute("case") Case theCase,
                                 @ModelAttribute("order") Order theOrder,
                                 Model theModel) {

        System.out.println("Executing the addCaseToOrderMethod");
        theCase.evaluation();
        theOrder.addCase(theCase);
        theOrder.getCharge();
        System.out.println(theCase.toString());
        theModel.addAttribute("order", theOrder);
        System.out.println(theOrder.getCases().size());

        return "redirect:/continueOrder";
    }

    @GetMapping("/continueOrder")
    public String continueOrder(@ModelAttribute("order") Order theOrder,
                                Model theModel) {

        theModel.addAttribute("order", theOrder);

        Quantity tempQuantity = new Quantity();
        theModel.addAttribute("tempQuantity", tempQuantity);

        System.out.println("Executing the continueOrder method");
        System.out.println(theOrder.getCases().size());

        return "new-full-order";
    }
(...)

У меня все еще была проблема с фактом что мой tempCase был строкой. Поэтому я нашел грязное решение. Я прошу oop через Случаи, содержащиеся в Ордене, преобразовать их в Строки и сравнить с tempCase, который уже является Строкой. И когда я получаю совпадение, я использую найденный случай в качестве ключа для обновления количества. : D

Контроллер

(...)
    @PostMapping("/updateQuantity")
    public String updateQuantity(@ModelAttribute("tempQuantity") Quantity tempQuantity,
                                 @ModelAttribute("tempCase") String tempCaseString,
                                 @ModelAttribute("order") Order theOrder,
                                 Model theModel) {

        for (Case checkedCase : theOrder.getCaseList()) {
            if (checkedCase.toString().equals(tempCaseString)) {
                System.out.println("Found equal cases");
                theOrder.getCases().get(checkedCase).setQuantity(tempQuantity.getQuantity());
            }
        }

        theModel.addAttribute(theOrder);

        return "redirect:/continueOrder";
    }
(...)

Еще нужно кое-что почистить.

Спасибо за помощь А. Вольф!

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...