User
オブジェクトは、セッションに@SessionAttributes
という名前で格納されています。そして、セッションの値がnullのときはいつでも初期化するために、@ModelAttribute
で装飾された単純なメソッドです。@PathVariableと@ModelAttributeの値が重複しています
Userクラス:
@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;
}
...
コントローラー:
@RequestMapping("/item")
@Controller
@SessionAttributes({"user"})
public class MyController {
@ModelAttribute方法:
@ModelAttribute("user")
public User createUser(Principal principal) {
return userService.findByUsername(principal.getName());
}
すべて、この特定の方法以外で期待通りに動作するようです:
@RequestMapping(value = "/{id}", method = RequestMethod.GET)
public String showItem(@PathVariable("id") Long id, @ModelAttribute("user") User user,
Model uiModel) {
...
}
User.id
が@PathVariable("id")
に設定されています。私は@RequestParam
でもこれに遭遇したと信じています。私は、両方が同じ名前とタイプを持っているからです。 Spring's documentation(下記参照)を読んだ後、これは予想される動作であると仮定しています。
次のステップはデータバインディングです。 WebDataBinderクラスは、クエリー文字列パラメータやフォームフィールドを含むリクエストパラメータ名と名前でモデル属性フィールドを照合します。一致するフィールドは、必要に応じて型変換(Stringから対象フィールド型への変換)が行われた後に設定されます。
しかし、このシナリオはかなり一般的だと思いますが、他の人はどのようにこれを処理していますか?私の発見が正しいと思われ、これが予想される動作(またはバグ)である場合、これは非常にエラーが発生する可能性が高いです。
考えられる解決策:
- 変更
@PathVariable("somethingElse")
へ@PathVariable("id")
。動作しますが@RequestParamではそれほど簡単ではありません(たとえば、jqgridのリクエストパラメータidを他のものに変更する方法はわかりませんが、これは別の問題です)。 @PathVariable("id")
タイプをLongからIntに変更します。これにより、User.id
とid
のタイプは異なりますが、ロングへのキャストは醜いものになります:)- ここでは
@ModelAttribute
を使用せず、User
のDBに再度クエリしてください。他のメソッドと一貫性がなく、冗長なDBコールが必要です。
Aがハック第四オプション、あなたが順序を変更した場合 - '@ ModelAttribute'最初にして' @ PathVariable' 。 –
結果は同じでしたが、試してみる価値がありました。 – Ulises
はい、実際には、Userの一致するプロパティがuri変数から照合されることが後で分かります。あなたのアプローチはよく見える、私は答えとして1つを追加しました。 –