将对象从 Web 表单传递到 Spring 控制器时出现问题

Problem with passing objects from web form to Spring controller

我遇到了这样的问题: 如何将对象从 Web 表单传递到 Spring 控制器? (我也在使用 Hibernate 和 Thymeleaf)

我做的一切都像这里做的那样: 但它对我不起作用.我收到这样的错误:

对象 'car' 字段 'engine' 中的字段错误:拒绝值 [1];代码 [typeMismatch.car.engine,typeMismatch.engine,typeMismatch.ua.klieshchunov.spring.memorial.model.entity.Engine,typeMismatch];参数 [org.springframework.context.support.DefaultMessageSourceResolvable:代码 [car.engine,引擎];参数 [];默认消息[引擎]];默认消息 [无法将类型 'java.lang.String' 的 属性 值转换为 属性 'engine' 所需的类型 'ua.klieshchunov.spring.memorial.model.entity.Engine';嵌套异常是 java.lang.IllegalStateException:无法将类型 'java.lang.String' 的值转换为 属性 所需的类型 'ua.klieshchunov.spring.memorial.model.entity.Engine' 'engine':找不到匹配的编辑器或转换策略]

我明白这个错误是什么意思。它试图将所选选项的值放入 Engine 类型的 Car 对象的字段中。但是我不明白,如何让它工作:P

这是与这个问题相关的所有代码

汽车

@Entity
@Table(name="cars")
@Data
@NoArgsConstructor
@AllArgsConstructor
public class Car {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Column(name="car_id")
    private int id;

    @Column(name="car_model")
    @Size(min=1, max=50, message="Model should be between 1 and 50 characters")
    private String model;

    @Column(name="car_price")
    @Min(value=0, message="The value must me positive")
    private int price;

    @ManyToOne(optional = false, cascade = CascadeType.ALL)
    @JoinColumn(name="engine_id")
    private Engine engine;
}

引擎

@Entity
@Table(name="engines")
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Engine {
    @Id
    @Column(name="engine_id")
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private int id;

    @Column(name="model")
    @Size(min=1, max=50, message="Model should be between 1 and 50 characters")
    private String model;
}

CarController(控制器)

 @GetMapping("/new")
    public String newCar(@ModelAttribute("car") Car car,
                         Model model) {
        model.addAttribute("engines", engineDAO.retrieve());
        return "/car/new";
    }

    @PostMapping("/save")
    public String create(@Valid @ModelAttribute("car") Car car,
                         BindingResult bindingResult,
                         Model model) {
        if (bindingResult.hasErrors()) {
            for (ObjectError objectError : bindingResult.getAllErrors()) {
                System.out.println(objectError);
            }
            model.addAttribute("engines", engineDAO.retrieve());
            return "/car/new";
        }
        carDAO.create(car);
        return "/car/index";
    }

new.html(查看)

...

<form th:method="POST" th:action="@{/car/save}" th:object="${car}">
    ...
    <label for="engine">Choose engine: </label>
    <select th:field="*{engine}" id="engine">
        <option th:each="dropDownItem : ${engines}"
                th:value="${dropDownItem.id}"
                th:text="${dropDownItem.model}" >
        </option>
    </select>

    <br/>
    <input type="submit" value="Create">

</form>
...

我需要做的就是将 select 块的 th:field 值从 "*{engine}" 更改为 "*{engine.id}" 形式。

new.html

...
<select th:field="*{engine.id}" id="engine">
    
    <option th:each="dropDownItem : ${engines}"
            th:value="${dropDownItem.id}"
            th:text="${dropDownItem.model}" >
    </option>

</select>
...

然后在控制器中,我在数据库中找到所需的记录(具有所选 ID 的引擎)并将填充的引擎对象设置为我的 Сar 对象,我已经从表单中获得了所有其他条目

汽车控制器

@PostMapping("/save")
public String create(@Valid @ModelAttribute("car") Car car,
                     BindingResult bindingResult,
                     Model model) {
    if (bindingResult.hasErrors()) {
        for (ObjectError objectError : bindingResult.getAllErrors()) {
            System.out.println(objectError);
        }
        model.addAttribute("engines", engineDAO.retrieve());
        return "/car/new";
    }
    car.setEngine(engineDAO.read(car.getEngine().getId()));
    carDAO.create(car);
    return "redirect:/car";
}

是的,晚上编码并不是一个好主意 xD