我正在尝试删除表单中的一个值。
public class Parameter {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "param_id")
private Long id;
@Column(name = "param_name")
@NotEmpty
private String name;
@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "param_id", referencedColumnName = "param_id")
private List<ParamValue> values;
}
和
public class ParamValue {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
@Column(name = "value_id")
private Long id;
@Column(name = "value_name")
private String name;
@ManyToOne(cascade = CascadeType.ALL)
@JoinColumn(name="param_id")
private Parameter parameter;
}
形式:
<form:form method="post" modelAttribute="parameter">
<form:input path="name" />
<c:forEach items="${parameter.values}" var="paramValue" varStatus="uStatus">
<div>
<form:input path="values[${uStatus.index}].id" type="hidden"/>
<form:input path="values[${uStatus.index}].name" type="text" />
<form:input path="values[${uStatus.index}].parameter" type="hidden" />
<button type="button" onclick="$(this).parent().remove();">x</button>
</div>
</c:forEach>
<input type="submit" value="save" class="btn btn-success">
</form:form>
在我的数据库中存在下一个值:
帕拉姆中的:
------------------
| id | name |
------------------
| 3 | TestParam |
------------------
在ParamValue中:
-----------------------------
| id | name | parameter |
-----------------------------
| 116 | value 1 | 3 |
-----------------------------
| 117 | value 2 | 3 |
-----------------------------
| 119 | value 3 | 3 |
-----------------------------
| 152 | value 4 | 3 |
-----------------------------
和控制器:
@Controller(value = "ParamsSave")
@RequestMapping("/params/save")
public class Save extends Base {
@Autowired
private ParamRepo paramRepo;
@ModelAttribute("parameter")
public Parameter getParam(@RequestParam(value = "id", required = false) Long param_id) {
if(param_id == null) {
return new Parameter();
}
Parameter parameter = paramRepo.findById(param_id);
return parameter == null ? new Parameter() : parameter;
}
@GetMapping
public String get(Parameter parameter) {
return getTemplate();
}
@PostMapping
public String post(@Valid Parameter parameter, BindingResult result) {
if(result.hasErrors()) {
return getTemplate();
}
paramRepo.save(parameter);
return "redirect: /";
}
}
如果我删除值“值2”,则出现错误:
beans.ParamValue实例的标识符从117更改为 119;嵌套异常是org.hibernate.HibernateException:identifier beans.ParamValue的实例从117更改为119
如果我删除了最后一个值,则没有任何反应,没有错误,字段也没有删除。
为什么会发生这种情况,如何从列表中删除值?
答案 0 :(得分:0)
我可以在您的代码中看到三个问题:
第一个是关联映射是错误的。在双向关联中,一方必须是拥有方,另一方必须是反向方。正确的映射如下:
@OneToMany(mappedBy = "parameter", cascade = CascadeType.ALL, orphanRemoval = true)
private List<ParamValue> values;
和
@ManyToOne
@JoinColumn(name="param_id")
private Parameter parameter;
请注意,我也删除了cascade=ALL
,因为它在@ManyToOne
的上下文中没有任何意义(您无法将ParameterValue
级联删除到其拥有{{1}例如,因为其他Parameter
仍会引用它,导致约束违例异常)。
话虽如此,我对是否需要双向关联存在严重怀疑。为什么不简单地将ParameterValue
映射为:
Parameter.values
并完全删除@OneToMany(cascade = CascadeType.ALL, orphanRemoval = true)
@JoinColumn(name = "param_id", referencedColumnName = "param_id")
private List<ParamValue> values;
字段?根据您所描述的用例来判断ParamValue.parameter
<{1}} 私有。ParamValues
无论如何。
另一个问题是HTML表单输入只能与简单值一起使用。我不完全确定以下行是做什么的:
Parameter
然而,有可能它没有达到预期的效果。无论如何,我不会依赖<form:input path="values[${uStatus.index}].parameter" type="hidden" />
处理程序中正确设置的ParameterValue.parameter
字段。如果您选择保留Save.post
字段,则应迭代ParameterValue.parameter
列表,并为每个元素手动设置字段。
最后,使用Parameter.values
表示提交的$(this).parent().remove()
数组中存在间隙(即原始对应于已删除元素的索引将丢失),这与您删除的观察结果一致最后一个值表现不同。您应该使用调试器检查parameter.values[]
收到的Parameter.values
的内容。