我已经查看了与此错误相关的其他线程,但无法弄清楚为什么我仍然遇到此问题。我相信问题出在我的HTML模板上。我正在尝试创建一个简单的下拉框,以选择要删除的“锻炼”列表。
HTML表单:
<form action="#" th:action="@{/workout/deleteWorkout}" th:object="${workout}" method="post">
<select th:field="*{workout}" name="workout" class="selectForm">
<option th:each="workout : ${workouts}"
th:value="${workout.workoutID}"
th:text="${workout.workoutName}">
</option>
</select>
<input type="submit" class="input-box">
</form>
页面的控制器方法:
@GetMapping("/workout/deleteWorkout")
public String deleteWorkoutForm(Model model,
HttpServletRequest request) {
Account account = (Account) request.getSession().getAttribute("loggedInUser");
model.addAttribute("workouts", workoutService.getWorkouts(account));
return "deleteWorkout";
}
@PostMapping("/workout/deleteWorkout")
public String deleteWorkout(@ModelAttribute Workout workout){
workoutService.deleteWorkout(workout);
return "workoutDeleted";
}
错误:
org.springframework.beans.NotReadablePropertyException: Invalid property 'workout' of bean class [depaul.tables.Workout]: Bean property 'workout' is not readable or has an invalid getter method: Does the return type of the getter match the parameter type of the setter?
感谢您的帮助。我特别困惑,因为在另一种方法中,我没有问题可以使用下拉框选择锻炼功能。谢谢!
编辑: 锻炼:
@Entity
public class Workout implements Serializable, IWorkout {
public Workout(){
}
public Workout(String accountName, String workoutName, String description, String workoutDate){
this.accountName = accountName;
this.workoutName = workoutName;
this.description = description;
this.workoutDate = workoutDate;
}
private String accountName;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long workoutID;
@NotNull
private String workoutName;
private String description;
private String workoutDate;
@OneToMany(cascade = CascadeType.ALL,
fetch = FetchType.EAGER,
mappedBy = "workout")
@Nullable
private Collection<Exercise> exercises = new ArrayList<Exercise>();
public String getAccountName() {
return accountName;
}
public void setAccountName(String accountName) {
this.accountName = accountName;
}
@Override
public Long getWorkoutID() {
return workoutID;
}
@Override
public void setWorkoutID(Long workoutID) {
this.workoutID = workoutID;
}
@Override
public String getWorkoutName() {
return this.workoutName;
}
@Override
public void setWorkoutName(String workoutName) {
this.workoutName = workoutName;
}
@Override
public String getDescription() {
return description;
}
@Override
public void setDescription(String description) {
this.description = description;
}
@Override
public String getWorkoutDate() {
return this.workoutDate;
}
@Override
public void setWorkoutDate(String workoutDate) {
this.workoutDate = workoutDate;
}
@Override
public Collection<Exercise> getExercises() {
return exercises;
}
@Override
public void setExercises(Collection<Exercise> exercises) {
this.exercises = exercises;
}
答案 0 :(得分:1)
我认为正在发生的事情是,百里香正试图将名为“锻炼”的select th:field="*{workout}" name="workout" class="selectForm">
的选择绑定到不属于该类的public class Workout
的属性。
由于您要设置的实际值为workoutID
,因此我将其命名为字段
<select th:field="*{workoutID}" name="workout" class="selectForm">
因此,百里香将参数绑定到setWorkoutID()
。而不是查找不存在的属性的setWorkout()
。
希望这会有所帮助!
编辑1:
由于在控制器中期望有一个@ModelAttribute称为'workout'且类型为Workout.class
,因此在页面呈现时,servlet引擎正在寻找该对象以将其绑定到Request。因此,您需要将此行添加到deleteWorkoutForm()
方法中:
model.addAttribute("workout", new Workout());
这将初始化对象并将其绑定到RequestContext中的模型。