¿Cómo rellenar previamente un objeto antes de actualizar usando spring mvc e hibernate?

¿Cuál es la mejor práctica para rellenar previamente un objeto antes de guardar este objeto con hibernación?

Qué he hecho:

Mi controlador:

//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";
    }
}

Funciona si hago un formulario que contiene todos los campos (nombre de usuario, contraseña e identificación), pero ¿qué debo hacer si quiero que el usuario actualice solo la contraseña?

Como tengo un @NotEmpty en el nombre de usuario, aparece un error de que el nombre de usuario es nulo, ya que no está en el formulario, pero no quiero poner el campo de nombre de usuario, solo la contraseña.

Mi formulario 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>
  • Intenté usar @Sessionattributes, pero no funciona bien si trato de editar dos o más usuarios usando las pestañas del navegador.
  • Intenté usar editores de propiedades, pero no funcionó con el usuario @ModelAtrribute User.
  • Intenté usar convertidores pero no funcionó.

¿Es la única forma de hacer que un usuario use = userService.find (id) primero y luego establecer los valores actualizados? Algo como:

@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";
}
}

Lo cual ve mal, porque no hay validación.

preguntado el 22 de mayo de 12 a las 16:05

4 Respuestas

Una forma alternativa, que creo que es menos complicada y propensa a los accidentes, es crear una clase que modele el formulario de la interfaz de usuario, por ejemplo.

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

y en el controlador update(EditUserForm,...) método, simplemente asigna cualquier campo rellenado por el usuario en el EditUserForm a la instancia de User desea actualizar.

contestado el 22 de mayo de 12 a las 16:05

Que se parece a mi último ejemplo (pero el mío tiene dos objetos, uno de ModelAttribute y otro de UserService), pero no pasará el @Valid y no devolverá errores al formulario con BindingResult. Solo si pongo la validación de hibernación tanto en EditUserForm como en User. ¿Me equivoqué? - Kenji

lo siento si no fui claro, pero lo que estoy sugiriendo es que el controlador no pone un User en el modelo ni que el update() El método contiene un User en su firma. edit() debe poner una instancia de la EditUserForm objeto de respaldo de forma en el modelo, y el update() la firma del método debería verse como update(@ModelAttribute("user") @Valid EditUserForm userForm, BindingResult result, RedirectAttributes redirectAttrs) - mate b

Perdón por esas preguntas, pero como puede ver, soy nuevo en el mundo de java/spring/hibernate, y estoy haciendo todo lo posible para hacerlo de la manera correcta. Así que déjame ver si entendí: 1. crea una clase UserEditForm y coloca una anotación de validación dentro de ella; 2. en mi método de controlador edit (), debo crear una instancia de UserEditForm y establecer sus propiedades usando userService.find (id) y enviarlo a la vista; 3 cuando lo recibo en la actualización del método del controlador (), debo enviar UserEditForm a userService.changePassword (UserEditForm) y luego debo hacer user.setPassword (UserEditForm.getPassword ())? - Kenji

Eso es principalmente lo que quiero decir, excepto que sugeriría que para el n. ° 3, el controlador update() asumir la responsabilidad de mapear desde un UserEditForm a una User objeto a pasar userService.update(User). Usar un objeto de respaldo de formulario como este en Spring MVC es un patrón bastante común. - mate b

En el código que publicó, obviamente está claro que necesita algunas clases auxiliares externas para asociarlas con la actualización del lado de la GUI antes de implementar las operaciones de control de movimiento y persistencia.

contestado el 22 de mayo de 12 a las 16:05

También me encontré con este problema, si solo hay un par de campos, uso su segundo ejemplo y valido los campos uno por uno. De lo contrario, tendrá que hacer lo que han dicho los otros carteles y crear una nueva clase para que coincida con su forma.

contestado el 22 de mayo de 12 a las 17:05

Tratar de usar:

@prepersistir
@PreActualización
preparación de vacío público () {
  //HAGA ALGO CON SU ENTIDAD //Por ejemplo: if(name==null){ name="MYNAMEVALUE";}
}

contestado el 22 de mayo de 12 a las 17:05

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.