【问题标题】:How to prepopulate an object before updating using spring mvc and hibernate?如何在使用spring mvc和hibernate更新之前预填充对象?
【发布时间】:2012-05-22 15:36:02
【问题描述】:

在使用 hibernate 保存对象之前预填充对象的最佳做法是什么?

我做了什么:

我的控制器:

//The Form
@RequestMapping(value = "user/{id}/edit", method = RequestMethod.GET)
public String edit(@PathVariable("id") Long userId, ModelMap modelMap) {
    modelMap.addAttribute("user", userService.find(userId));    
    return "user/userEdit";

}
//Updating database
@RequestMapping(value = "user/edit", method = RequestMethod.POST)
public String update(@ModelAttribute("user") @Valid User user, BindingResult result,
                                                RedirectAttributes redirectAttrs) {
    if (result.hasErrors()) {
            return "user/userEdit";
    }else{
        userService.update(user);
        redirectAttrs.addFlashAttribute("message", "Success");

        return "redirect:user/userEdit";
    }
}

如果我创建一个包含所有字段(用户名、密码和 ID)的表单,它会起作用,但是如果我希望用户只更新密码,我应该怎么做?

由于我在用户名处有一个@NotEmpty,我收到一个错误,即用户名为空,因为它不在表单中,但我不想输入用户名字段,只输入密码。

我的 html 表单:

<c:url var="url" value="/user/edit" />
<form:form method="post" action="${url}" modelAttribute="user" class="form-horizontal">
    <form:hidden path="id"/>
    <form:hidden path="version"/>
    <fieldset>
        <div class="control-group">
            <form:label cssClass="control-label" path="password"><spring:message code="user.label.password"/>: </form:label>
            <div class="controls">
                <form:input cssClass="input-xlarge" path="password" />
            </div>
            <form:errors path="password"/>
        </div>
        <div class="control-group">
            <form:label cssClass="control-label" path="userRole"><spring:message code="user.label.role"/>: </form:label>
            <div class="controls">
                <form:select path="userRole">
                       <form:options items="${userRoleList}" itemValue="id" itemLabel="name"/>
                </form:select>
            </div>
            <form:errors path="userRole"/>
        </div>
        <div class="control-group">
            <form:label cssClass="control-label" path="costumer.id"><spring:message code="user.label.costumer"/>: </form:label>
            <div class="controls">
                <form:select path="costumer.id">
                       <form:options items="${costumerList}" itemValue="id" itemLabel="name"/>
                </form:select>
            </div>
            <form:errors path="costumer.id"/>
        </div>

        <div class="form-actions">
            <button type="submit" class="btn btn-primary">Save changes</button>
            <a class="btn cancel link" href="<c:url value="/user" />">Cancel</a>
        </div>
    </fieldset>
</form:form>
  • 我尝试使用@Sessionattributes,但如果我尝试使用它就无法正常工作 使用浏览器选项卡编辑两个或更多用户。
  • 我尝试使用属性编辑器,但无法使用 @ModelAtrribute 用户用户。
  • 我尝试使用转换器,但没有成功。

唯一的方法是先让用户 user = userService.find(id) ,然后设置更新的值吗?比如:

@RequestMapping(value = "user/edit", method = RequestMethod.POST)
public String update(@RequestParam("password") String password, BindingResult result, RedirectAttributes redirectAttrs) {
    User user = userService.find(id);
if (password == null{                           
    return "user/userEdit";
}else{
    user.setPassword("password");
    userService.update(user);
    redirectAttrs.addFlashAttribute("message", "Success");

    return "redirect:user/userEdit";
}
}

这看错了,因为没有验证。

【问题讨论】:

    标签: java spring hibernate spring-mvc


    【解决方案1】:

    另一种我认为不那么混乱和容易发生意外的方法是创建一个模拟 UI 表单的类,例如

    public class EditUserForm {
        // getters and setters for password and other fields...
    }
    

    在控制器的update(EditUserForm,...) 方法中,您只需将用户在EditUserForm 中填充的任何字段映射到您希望更新的User 实例。

    【讨论】:

    • 这看起来像我的最后一个示例(但我的有两个对象,一个来自 ModelAttribute,另一个来自 UserService),但它不会传递 @Valid 并且不会使用 BindingResult 向表单返回错误。仅当我在 EditUserForm 和 User 中都进行休眠验证时。我弄错了吗?
    • 对不起,如果我不清楚,但我的建议是控制器没有将 User 放入模型中,update() 方法在其签名中包含 Useredit() 应该将EditUserForm form-b​​acking 对象的实例放入模型中,update() 方法签名应该类似于update(@ModelAttribute("user") @Valid EditUserForm userForm, BindingResult result, RedirectAttributes redirectAttrs)
    • 抱歉这些问题,但正如您所见,我对 java/spring/hibernate 世界很陌生,并且尽我所能以正确的方式做到这一点。所以让我看看我是否理解: 1. 创建一个 UserEditForm 类并在其中放置验证注释; 2. 在我的 edit() 控制器方法中,我应该创建一个 UserEditForm 实例并使用 userService.find(id) 设置其属性并将其发送到视图; 3 当我在控制器方法 update() 上收到它时,我应该将 UserEditForm 发送到 userService.changePassword(UserEditForm) 然后我应该执行 user.setPassword(UserEditForm.getPassword())?
    • 这主要是我的意思,除了我建议#3控制器的update()方法负责从UserEditForm映射到User对象传递到@987654335 @。在 Spring MVC 中使用这样的表单支持对象是一种非常常见的模式。
    【解决方案2】:

    在您发布的代码中,很明显您需要一些外部帮助类来与您的 GUI 端更新相关联,然后才能实现移动控制和持久性操作。

    【讨论】:

      【解决方案3】:

      我也遇到过这个问题,如果只有几个字段,我会使用您的第二个示例并逐个验证字段。否则,您将不得不按照其他发帖者所说的去做,并创建一个与您的表单相匹配的新课程。

      【讨论】:

        【解决方案4】:

        尝试使用:

        @PrePersist
        @PreUpdate
        公共无效准备(){
        //对你的实体做点什么 //例如:if(name==null){ name="MYNAMEVALUE";}
        }

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多