我仍然在与Spring MVC苦苦挣扎,这应该是一个相当直接的问题,但Spring MVC文档中似乎更少。Spring MVC复杂对象数据绑定
我的项目使用Spring MVC和Thymeleaf的意见,但视图渲染引擎是不是真正的问题有关。
我的申请是围绕活动类模型是由一个部件,并且其中其他成员可以订阅组织的(室内或室外)活性居中。一个Activity包含一个Category字段和一个Region字段,它们是由Hibernate建模为多对一实体的下拉字段,包含一个id和description字段的DB查找表。
为活动实体类的代码如下,非相关字段被省略,以缩短的代码:
package nl.drsklaus.activiteitensite.model;
//imports
@Entity
@Table(name="activity")
public class Activity {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
private Integer id;
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name="organizer_id")
private Member organizer;
@Size(min=5, max=50)
@Column(name = "title", nullable = false)
private String title;
@Size(min=5, max=500)
@Column(name = "description", nullable = false)
private String description;
@ManyToOne
@JoinColumn(name="category_id")
private ActivityCategory category;
@ManyToOne
@JoinColumn(name="region_id")
private ActivityRegion region;
@ManyToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER)
@JoinTable(name="member_activity_subscription",
joinColumns = {@JoinColumn(name="activity_id")},
inverseJoinColumns={@JoinColumn(name="member_id")})
private List<Member> participants = new ArrayList<Member>();
//getters and setters
@Override
public int hashCode() {
...
}
@Override
public boolean equals(Object obj) {
...
}
}
在视图中,用户应能够从选择的区域和类别选择框。在类级别使用@ModelAttribute注释方法将选项放入模型中。
问题在于该框与查找属性字段的绑定。
例如类别字段是ActivityCategory类型,它是含有一个ID和一个描述性的实体类的。
在视图中,选择框填充有可能的选项(allCategories含有ActivityCategory实例)的列表中,Thymeleaf取得由“value”属性值与列表匹配选择的电流值的方式:
<label>Categorie</label>
<select th:field="*{category}">
<option th:each="cat : ${allCategories}"
th:value="${cat}"
th:text="${cat.description}">
</option>
</select>
生成的HTML看起来像:
<select id="category" name="category">
<option value="[email protected]">Actief en sportief</option>
<option value="[email protected]">Uitgaan en nachtleven</option>
<option value="[email protected]" selected="selected">Kunst en cultuur</option>
<option value="[email protected]">Eten en drinken</option>
<option value="[email protected]" selected="selected">Ontspanning en gezelligheid</option>
</select>
正如我们看到的,值属性包含这显然是不希望对象本身的字符串表示,以显示我们可以用$ {猫的ID值。 id}而不是$ {cat }但是然后选择当前值(设置'selected =“selected''属性)不再有效。因此,我实现了一个Converter,它将ActivityCategory对象转换为int(id值)。在Thymeleaf,转换器通过使用双赞誉称为{{}}:
th:value="${{cat}}"
转换器创建并添加到春:
public class LookupConverter implements Converter<LookupEntity, String> {
public String convert(LookupEntity source) {
return String.valueOf(source.getId());
}
}
//在MvcConfig类
@Override
public void addFormatters(FormatterRegistry registry) {
registry.addConverter(new LookupConverter());
}
现在HTML显示选项的id值,这更合乎逻辑:
<select id="category" name="category">
<option value="1">Actief en sportief</option>
<option value="2">Uitgaan en nachtleven</option>
<option value="3" selected="selected">Kunst en cultuur</option>
<option value="4">Eten en drinken</option>
<option value="5">Ontspanning en gezelligheid</option>
</select>
但是它在提交后仍然出错,无法将id值绑定到期望ActivityCategory的Activity对象,而不是整数值,因此会生成typeMismatch验证错误。
我的处理方法是这样的:
@RequestMapping(value = "/{id}/submit", method = RequestMethod.POST)
public String submitForm(@ModelAttribute("activity") Activity activity, BindingResult result, ModelMap model) {
if (result.hasErrors()) {
return "activityform";
} else {
if (activity.getId() == null) {
this.service.saveActivity(activity);
} else {
this.service.mergeWithExistingAndUpdate(activity);
}
return "redirect:/activity/" + activity.getId() + "/detail";
}
}
我已经看了很多帖子,但仍发现有这个恕我直言,很琐碎的问题没有解决。包含id的字符串值如何被处理程序方法接受并正确转换?或者我们不能使用id值来达到这个目的吗? 寻找一些提示...
谢谢您的回答,如果不是所有的例子实际上确实使用了实体模型对象作为表单对象。事实上反对使用单独的表单支持对象的Spring MVC的文件建议: _“因此,你不必复制你的业务对象的属性,如您的表单对象简单的无类型字符串简单地处理无效的意见,或者对字符串转换正确的。相反,它往往是直接绑定到你的业务对象。“_ 但事实如此仍不明朗我如何处理这个最例子并不从单独的实体使用查找字段。 – klausch