Ho un oggetto User
memorizzato nella sessione con @SessionAttributes
. E un metodo straight-forward decorato con @ModelAttribute
per inizializzarlo ogni volta che il valore della sessione è nullo.Valori di @PathVariable e @ModelAttribute che si sovrappongono
utente:
@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;
}
...
Controller:
@RequestMapping("/item")
@Controller
@SessionAttributes({"user"})
public class MyController {
metodo @ModelAttribute:
@ModelAttribute("user")
public User createUser(Principal principal) {
return userService.findByUsername(principal.getName());
}
Tutto sembra funzionare come previsto se non in questo particolare metodo:
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public String showItem(@PathVariable("id") Long id, @ModelAttribute("user") User user,
Model uiModel) {
...
}
Il problema è che User.id
sia impostata con @PathVariable("id")
. Credo di essermi imbattuto in questo con @RequestParam
. Suppongo che sia perché hanno lo stesso nome e tipo. Dopo aver letto Spring's documentation (vedi sotto) presumo che questo comportamento sia previsto:
Il passaggio successivo è il collegamento dei dati. La classe WebDataBinder corrisponde ai nomi dei parametri di richiesta, inclusi parametri della stringa di query e campi modulo, per modellare i campi degli attributi in base al nome. I campi di corrispondenza vengono popolati dopo che la conversione del tipo (da stringa al tipo di campo di destinazione) è stata applicata laddove necessario.
Tuttavia, penso che questo scenario sia abbastanza comune, come lo gestiscono le altre persone? Se i miei risultati sono corretti e questo è il comportamento previsto (o bug), questo sembra essere molto incline agli errori.
Possibili soluzioni:
- Change
@PathVariable("id")
a@PathVariable("somethingElse")
. Funziona ma non è così semplice con @RequestParam (ad esempio, non so come cambiare l'ID del parametro di richiesta di jqgrid in qualcos'altro, ma questo è un altro problema). - Cambia
@PathVariable("id")
tipo da Lungo a Int. Questo renderà i tipiUser.id
eid
diversi, ma il cast su Long sembra brutto :) - Non utilizzare
@ModelAttribute
qui e richiedere nuovamente il DB perUser
. Non coerente con altri metodi e comporta chiamate DB ridondanti.
Qualche suggerimento?
un hack quarta opzione, che cosa succede se si cambia l'ordine - '@ ModelAttribute' prima e poi' @ PathVariable' . –
Il risultato è stato lo stesso, comunque vale la pena provare. – Ulises
Sì, in realtà ho realizzato in seguito che le proprietà corrispondenti dell'utente verranno confrontate dalle variabili uri. I tuoi approcci sembrano buoni, ne ho aggiunto uno in più come risposta. –