Spring MVC表单后备对象在未绑定时具有null属性

时间:2014-03-19 13:04:36

标签: spring-mvc jpa

我发现了许多与我相近的问题,但讨论总是回到同一个解决方案(DTO方法)。我面临的问题如下:

我有一个表格的以下支持对象作为JPA实体列表:

public class PlayerForm {
private List<Player> players;

public List<Player> getPlayers() {
    return players;
}

public void setPlayers(List<Player> players) {
    this.players = players;
}

}

以下对象的列表:

@Entity
public class Player implements Serializable {

/**
 * 
 */
private static final long serialVersionUID = 1L;
public enum PlayerType{
    DEV, POQA;
}
@Id
private Long id;
@Column(unique=true)
private String name;
private int score;

@Enumerated(EnumType.STRING)
private PlayerType playerType;


@ManyToMany
private List<Bonus> bonusItems;

我将PlayerForm传递给模型并使用我视图中的forllowing表单将其绑定:

<form:form method="POST" action="${action}"
modelAttribute="playerForm">
<table class="${cssClass}">
    <tr>
        <th>Rank</th>
        <th>Name</th>
        <th>Score</th>
    </tr>
    <c:forEach items="${playerForm.players}" var="player" varStatus="status">
        <tr>
            <td class="center">${status.count}</td>
            <td>${player.name}</td>
            <td><input name="players[${status.index}].id" type="hidden"
                value="${player.id}" /><input name="players[${status.index}].name" type="hidden"
                value="${player.name}" /><input name="players[${status.index}].score" type="number"
                value="${player.score}" /></td>
        </tr>
    </c:forEach>
</table>
<input style="width: 25%;" onclick="clearPreviousMessages();"
    type="submit" value="Submit Changes" />
</form:form>

提交表单后,未映射到表单输入的属性将被清零。我知道我可以使用我的实体的DTO抽​​象,这将解决问题。但是,有没有办法让spring mvc只将我的输入值绑定到属性,同时保持传递给模型的其他属性的初始值,即使它们没有绑定到任何输入?

1 个答案:

答案 0 :(得分:0)

如CodeChimp所述,您需要首先加载完整的 PlayerForm 实例,并在请求之间保持其状态。您通常使用会话来执行此操作,但Spring MVC具有 @SessionAttributes 构造,可帮助您在控制器范围内维护后续请求之间的模型属性状态。

尝试使用以下元代码示例来说明它

@Controller
@SessionAttributes("playerForm")
public class FormController {

    @RequestMapping("/init")
    public String start(Model model) {
        PlayerForm playerForm = initialiaze(); // e.g. load from DB
        model.addAttribute("playerForm", playerForm);
        return "form"; // return to the form
    }

    @RequestMapping(method=RequestMethod.POST)
    public String processSubmit(@ModelAttribute("playerForm") PlayerForm playerForm) {
        // do something, make changes, store in DB, whatever
        return "form"; // return to the form
    }

    @RequestMapping("/finishEdit")
    public String end(SessionStatus status) {
        status.setComplete(); // remove the model attribute from the session
        return "nextpage"; // move to a different page
    }
}

最初,您的表单页面已加载到 / init ,并且 PlayerForm 对象已初始化并添加到模型中,您的表单将呈现所有数据。

更改数据和提交表单由processSubmit处理,但在调用方法之前,由于 @SessionAttributes(“playerForm”) @ModelAttribute(“playerForm”的绑定“) playerForm将从会话中获取先前的值,而不是使用表单中的值进行更新,最后,将再次更改会话中的值,并再次呈现表单。此循环将使您的所有后续请求按预期工作(不会创建空值)

最后,当使用表单导航离开页面时,应设置 status.setComplete ,以便从会话中删除模型属性