2012-12-22 15 views
5

Spring MVCモデルBeanの一部のみを表示する場合、ブラウザから戻ってくるものをモデルで更新する方法がありますか?Spring MVC + Hibernate:ブラウザからの部分モデルの更新

のは、我々は(もちろんこの例のみでのパブリックプロパティ、)Userクラスがあるとしましょう:

public class User { 
    public String firstName; 
    public String lastName; 
    public String email; 
    public Date subscriptionExpiration; 
} 

は今、私はJSPの入力フィールドとして、最初の3つのプロパティを表示し、中のオブジェクトを更新したいですそれに応じてデータベース。これらの3つのパラメータだけが更新されるべきであり、第4のパラメータは更新されるべきではない。これを実現するための一つの方法は

@RequestMapping("/user/{userId}", method=RequestMethod.POST) 
public String saveChanges(@PathVariable userId, User user, Model model) { 
    User oldUser = User.loadFromDB(userId); 
    oldUser.firstName = user.firstName; 
    oldUser.lastName = user.lastName; 
    oldUser.email = user.email; 
    oldUser.saveToDB(); 

    model.addAttribute("user", oldUser); 
} 

だろうが、これは、私はあまり好きではありませんこれは、変更される可能性があり、すべてのプロパティをハードコーディングを意味します。

ユーザーが変更を許可された内容に基づいて、更新するフィールドを判断する方法はありますか?そのメカニズムは、要求パラメータにあるすべてのものが変更される可能性があると仮定するだけでなく、精通したユーザーが手作業で追加のフィールドを要求に挿入することができると想定するよりもスマートにすべきです。

@Entity(dynamicUpdate = true)を使用しても、私の目には問題は解決しません。ユーザーオブジェクト全体が要求に戻らないため、多くのセキュリティホールが発生します。

私は春に素敵な機能が欠けていますか、あるいは概念的にこの問題を解決する他の方法はありますか?どんなヒントも大歓迎です!

答えて

3

@InitBinderを使用して、いくつかのモデルフィールドをSpringがパラメータを要求するためにバインドできるようにする方法を知るには、this questionを参照してください。これにより、subscriptionExpirationがリクエストパラメータを注入することによって変更できないことを確認できます。

@RequestMappingメソッドが呼び出される前に、メソッドとメソッド引数に@ModelAttributeアノテーションを使用してデータベースからユーザーをロードしてモデルに追加する方法と、このユーザーに要求パラメータを設定する方法については、the documentationを参照してください。 @RequestMappingメソッドが呼び出されたとき。これにより、DBからユーザを取得し、Springが要求から来る値をそれに設定するようにします。あなたがしなければならないのは、ユーザーの新しい状態を検証し、それをデータベースに保存するだけです。

2

私は方法

BeanUtils.copyProperties(Object source, Object target, String[] ignoreProperties) 

が何をしたいんだと思います。 String[] ignorePropertiesで定義されているプロパティに触れることなく、あるオブジェクトから別のオブジェクトにすべてのプロパティをコピーします。

与えられたソースBeanのプロパティ値を、指定した "ignoreProperties"を無視して、指定したターゲットBeanにコピーします。

注:プロパティと一致する限り、ソースクラスとターゲットクラスは、一致する必要はなく、互いに派生する必要もありません。ソースBeanが公開しているがターゲットBeanは公開していないBeanプロパティはすべて自動的に無視されます。

これは単なる便利な方法です。より複雑な転送の必要性については、完全なBeanWrapperの使用を検討してください。

API Documentation

+0

当分の間、このようなことをしました。フィールド上でカスタムアノテーションを使用して、それらが更新されるかどうかを調整し、ignorePropertiesのリストを作成するように解析しています。それはうまくいきますが、私はこれを手動で定義することを避けたいと思います。しかし、入力をありがとう! – usimon

0

あなたはまず、データベースからオブジェクトを読み取り、その要求をバインドすることができます。例はFuWeSta-Sampleです。

これは、helper-beanを使用します。これは、Springで初期化する必要があります。

0

1つのオプションは、フォームに隠しフィールドを使用することです。ドローバック付きのオプションですが、場合によっては機能します

0

お探しの素敵な機能は@ModelAttributeです。私はあなたのフォームはまた、ユーザーIDを投稿すると仮定します。

public class UserController { 

    @ModelAttribute 
    public User getUser(@RequestParam(value = "id", required = false) Long id) { 
     return User.loadFromDB(id); 
    } 

    @RequestMapping("/user/{id}", method=RequestMethod.POST) 
    public String saveChanges(@ModelAttribute User user, BindingResult bindingResult, Model model) { 

     if (bindingResult.hasErrors()) { 
      // return ... 
     } 

     // model.asMap().clear(); 

     user.saveToDB(); 
     // return ... 
    } 
} 
関連する問題