我仍然在與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