2

Spring MVC Webアプリには、フォームと対応するコントローラーがあります。コントローラでは、ユーザーがフォームの値を変更したかどうかを知る必要があります。これにより、データベースのステータステーブルの「changed_on」列を更新するかどうかを知ることができます。

どのフィールドが変更されたかは気にせず、ユーザーのデータは関係なく保存します。しかし、ユーザーがA-> Bを変更してから、送信する前にAに戻った場合、その変更を考慮したくありません。ユーザーが実際にデータを変更している場合にのみ日付/時刻列を更新したいのは、ユーザーが最後にデータを変更したのは後で知る必要があるためです。

これを達成するための最良の方法は何ですか?バックエンドで行うのが良いですか、それともフロントエンドで行うのが良いですか?これは非常に一般的な問題のようです。ユーザーがフォームのデータを変更しているかどうかを確認する方法です。

私はいくつかの潜在的な解決策を考え出しました。私のフォームフィールドはブール値、整数、文字列、列挙型です。

フロントエンドソリューション

  1. JavascriptでonChangeまたはリスナーを使用して非表示のフォームフィールドを設定します。onBlur
  2. を使用してjQueryコールバック関数を使用し$("form :input").change()、を使用して値を.data()に設定します。changedtrue

バックエンドソリューション

  1. Webフォームが(私のコントローラーを介して)バインドされているフォームクラスで、変更の監視に関心のあるすべてのフィールドに基づいて@InitBinder("formName")オーバーライドします。hashCode()私はどのコレクションでもフォームクラスを使用していないか、Hibernateに渡していないため、これによる悪い副作用は想定していません。Guavaを使用した実装は次のとおりです。

    @Override
    public int hashCode() {
        return Objects.hashCode(this.field1, this.field2, etc.);
    }
    

    次に、(メソッドで作成された)古いフォームオブジェクトを、送信されたフォーム値からget()によって作成された新しいフォームオブジェクトと比較できます。WebDataBinderハッシュが異なる場合、ユーザーは何かを変更しました。

    このアプローチで私が持っている質問は、古いフォームオブジェクトをどのように保持するのかということです。ModelAndViewGETからPOSTまで存続するページにそれを詰め込む方法はありますか?doPost()または、データベースからベースになっている永続エンティティをリロードして、メソッドで再作成することはできますか?Hibernateがエンティティをキャッシュする場合、新しい変更を永続化する前に、元のフォームオブジェクトを再作成するのはかなり速いはずです。

  2. #1と同様ですが、個々のフィールドへのハードコードされた依存の代わりにリフレクションを使用します。hashCode()このように、新しいフォームフィールドが追加された場合、それらをメソッドに追加することを忘れないでください。実装は次のとおりです。

    public static boolean hasFormChanged(Object form1, Object form2) {
        return HashCodeBuilder.reflectionHashCode(form1) != HashCodeBuilder.reflectionHashCode(form2);
    }
    

    今、私は反射が遅いことを知っています。私のテストでは、上記のアプローチよりも約8〜12倍遅くなりますObjects.hashCode()。ただし、フォームフィールドは4つしかなく、ローカルマシンでのテストでは、リフレクションベースの方法は1回の呼び出しで約3.5マイクロ秒かかります。リフレクションのもう1つの欠点は、比較に含めたくない新しいインスタンス変数をフォームクラス(またはその親クラス)に追加することに注意する必要があることです。

4

1 に答える 1

1

フロントエンドソリューションの場合、任意のページに適用できるより一般的な例を実装できます。ページの読み込み時に、form要素を繰り返し処理してから、フォームのすべてのフィールドを繰り返し処理し、その名前と値を保存します

例えば、

["form1", {field1: "value1"}, {field2 : "value2"}]

送信する直前に、新しいフォームの値が古いフォームの値と等しいかどうかを確認し、「変更された」プロパティを追加できます。

すべてのフロントエンドソリューションは醜いです。もちろん、サーバー側で作成することをお勧めします

古いオブジェクトをhttpSessionに保存することも、2回目にリクエストすることもできます(hibernateはデフォルトでキャッシュを使用しないことに注意してください)。hashCode代わりに使用する意味は何equalsですか?同じオブジェクトが同じhashCodeを返さない場合、衝突の可能性はわずかです。

最も簡単なアプローチ-Dbからオブジェクトを2回要求し、equalsを使用してそれらを比較します

于 2012-05-01T16:15:47.590 に答える