Tengo un objeto User
almacenado en la sesión con @SessionAttributes
. Y un método directo decorado con @ModelAttribute
para inicializarlo cuando el valor de la sesión sea nulo.Valores de @PathVariable y @ModelAttribute superposición
usuario:
@Entity
@Table(name="USER")
public class User implements java.io.Serializable {
private Long id;
private String username;
private String password;
....
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name ="ID")
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
...
controlador:
@RequestMapping("/item")
@Controller
@SessionAttributes({"user"})
public class MyController {
método @ModelAttribute:
@ModelAttribute("user")
public User createUser(Principal principal) {
return userService.findByUsername(principal.getName());
}
Todo parece funcionar como se esperaba, excepto en este método particular:
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public String showItem(@PathVariable("id") Long id, @ModelAttribute("user") User user,
Model uiModel) {
...
}
El problema es que User.id
se está configurando con @PathVariable("id")
. Creo que me encontré con esto también con @RequestParam
. Supongo que es porque ambos tienen el mismo nombre y tipo. Después de leer Spring's documentation (ver a continuación), supongo que se espera que este comportamiento:
El siguiente paso es el enlace de datos. La clase WebDataBinder coincide con los nombres de parámetros de solicitud, incluidos los parámetros de cadena de consulta y los campos de formulario, para modelar los campos de atributo por nombre. Los campos coincidentes se rellenan después de que se haya aplicado la conversión de tipo (desde String al tipo de campo de destino) cuando sea necesario.
Sin embargo, creo que este escenario es bastante común, ¿cómo lo están manejando otras personas? Si mis hallazgos son correctos y este es el comportamiento esperado (o error), esto parece ser muy propenso a errores.
soluciones posibles:
- Cambio
@PathVariable("id")
a@PathVariable("somethingElse")
. Funciona, pero no es tan sencillo con @RequestParam (por ejemplo, no sé cómo cambiar el ID del parámetro de solicitud de jqgrid a otra cosa, pero este es otro problema). - Cambiar
@PathVariable("id")
tipo de Long a Int. Esto hará que los tiposUser.id
yid
difieran, pero el modelo a Largo se ve feo :) - No utilice
@ModelAttribute
aquí y consulte DB nuevamente paraUser
. No es coherente con otros métodos e implica llamadas DB redundantes.
¿Alguna sugerencia?
un hack cuarta opción, lo que si se cambia el orden - '@ ModelAttribute' primero y luego' @ PathVariable' . –
El resultado fue el mismo, valió la pena intentarlo. – Ulises
Sí, en realidad se dio cuenta más tarde de que las propiedades coincidentes del usuario se compararán con las variables uri. Sus enfoques se ven bien, he agregado uno más como respuesta. –