Spring MVC 错误:无法将 java.lang.String 类型的属性值转换为所需类型

IT小君   2022-09-15T08:09:31

我不能放过这个例外:

Failed to convert property value of type java.lang.String to required type com.company.springdemo.entity.Product for property productId; nested exception is java.lang.IllegalStateException: Cannot convert value of type java.lang.String to required type com.company.springdemo.entity.Product for property productId: no matching editors or conversion strategy found 

订单模式

@Entity
@Table(name = "orders") // naming the table only order, will throw exception
public class Order {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "order_id")
private Integer orderId;


@OneToOne(cascade = {CascadeType.DETACH,CascadeType.MERGE,CascadeType.PERSIST,CascadeType.REFRESH})
@JoinColumn(name = "product_id")
private Product productId;

@ManyToOne(fetch = FetchType.EAGER, cascade = {CascadeType.DETACH,CascadeType.MERGE,CascadeType.PERSIST,CascadeType.REFRESH})
@JoinColumn(name = "client_id")
private Client client;

....

产品型号

@Entity
@Table(name = "product")
public class Product {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "product_id")
private Integer id;

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

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

...

客户模型

@Entity
@Table(name = "clients")
public class Client {

@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Integer id;

@NotEmpty
@Column(name = "first_name")
private String firstName;

@NotEmpty
@Column(name = "last_name")
private String lastName;

@NotEmpty
@Email
@Column(name = "email")
private String email;

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

@OneToMany(mappedBy = "client",cascade = CascadeType.ALL, fetch = FetchType.EAGER)
private List<Order> orders;

控制器,我将订单与相关的客户和产品一起保存

@PostMapping("add")
public ModelAndView addOrder( @Validated @ModelAttribute("ords") Order order, BindingResult bindingResult ){

    if (bindingResult.hasErrors()) {
        System.out.println("Having errors: " + bindingResult.getAllErrors());

        Iterable<Product> products = productService.listProducts();
        Iterable<Client> clients = clientService.listClients();


        System.out.println("Error "+ bindingResult.getAllErrors());

        ModelAndView mv = new ModelAndView("orders/add-order");

        mv.addObject("products",products);
        mv.addObject("clients",clients);

        return mv;
    }

    try {
        orderService.saveOrder(order);
    } catch (Exception e) {
        e.printStackTrace();
    }

    ModelAndView mv = new ModelAndView("redirect:list");

    return mv;
}

最后是我的JSP表单查看页面

<form:form action="add" method="post" modelAttribute="ords">

    <label for="productId" >Product Id</label>
    <form:select path="productId" >
        <c:forEach var="product" items="${products}">
            <form:option value="${product.id}">${product.productName}</form:option>
        </c:forEach>
    </form:select>

    <form:errors path="productId"/>

    <br>

    <label for="client" >Client Id</label>
    <form:select path="client" >
        <c:forEach var="client" items="${clients}">
            <form:option value="${client.id}">${client.id} - ${client.lastName}</form:option>
        </c:forEach>
    </form:select>

    <form:errors path="client"/>

    <br>

    <input type="submit" value="Place Order">

</form:form>

我究竟做错了什么?

点击广告,支持我们为你提供更好的服务
评论(2)
IT小君

您很可能需要构建一个转换器类,例如:

@Component("facilityConverter")
public class FacilityConverter implements Converter<String, Facility>
{
    @Autowired
    FacilityService facilityService;

    @Override
    public Facility convert(String id) 
    {
        return facilityService.findById(Integer.parseInt(id));
    }
}

然后,您需要通过在实现 WebMvcConfigurer 的配置类中实现 addFormatters 方法来注册它,如下所示:

@Override
public void addFormatters (FormatterRegistry registry)
{
    registry.addConverter((FacilityConverter)ctx.getBean("facilityConverter"));
}

然后,您的实体将从下拉选择中正确映射。此外,这可能不是您的问题的一部分,但您可以像这样构建下拉列表:

<form:select name="linkedInterface" path="linkedInterface" id="linkedInterface">
                        <form:options items="${interfaces}" itemLabel="name" itemValue="id"/>
                    </form:select>
2022-09-15T08:09:31   回复
IT小君

productId字段实际上是一个Product对象,而不是一个 ID (String/int)。您需要使用 JSPpath="productId.id"而不是path="productId".

(尽管我还建议您也重命名该字段product而不是productId.)

<form:select path="product.id">

我想你也会遇到同样的问题<form:select path="client">

2022-09-15T08:09:31   回复