В моем приложении 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>
