Spring MVC Webアプリには、フォームと対応するコントローラーがあります。コントローラでは、ユーザーがフォームの値を変更したかどうかを知る必要があります。これにより、データベースのステータステーブルの「changed_on」列を更新するかどうかを知ることができます。
どのフィールドが変更されたかは気にせず、ユーザーのデータは関係なく保存します。しかし、ユーザーがA-> Bを変更してから、送信する前にAに戻った場合、その変更を考慮したくありません。ユーザーが実際にデータを変更している場合にのみ日付/時刻列を更新したいのは、ユーザーが最後にデータを変更したのは後で知る必要があるためです。
これを達成するための最良の方法は何ですか?バックエンドで行うのが良いですか、それともフロントエンドで行うのが良いですか?これは非常に一般的な問題のようです。ユーザーがフォームのデータを変更しているかどうかを確認する方法です。
私はいくつかの潜在的な解決策を考え出しました。私のフォームフィールドはブール値、整数、文字列、列挙型です。
フロントエンドソリューション
- Javascriptで
onChange
またはリスナーを使用して非表示のフォームフィールドを設定します。onBlur
- を使用してjQueryコールバック関数を使用し
$("form :input").change()
、を使用して値を.data()
に設定します。changed
true
バックエンドソリューション
Webフォームが(私のコントローラーを介して)バインドされているフォームクラスで、変更の監視に関心のあるすべてのフィールドに基づいて
@InitBinder("formName")
オーバーライドします。hashCode()
私はどのコレクションでもフォームクラスを使用していないか、Hibernateに渡していないため、これによる悪い副作用は想定していません。Guavaを使用した実装は次のとおりです。@Override public int hashCode() { return Objects.hashCode(this.field1, this.field2, etc.); }
次に、(メソッドで作成された)古いフォームオブジェクトを、送信されたフォーム値から
get()
によって作成された新しいフォームオブジェクトと比較できます。WebDataBinder
ハッシュが異なる場合、ユーザーは何かを変更しました。このアプローチで私が持っている質問は、古いフォームオブジェクトをどのように保持するのかということです。
ModelAndView
GETからPOSTまで存続するページにそれを詰め込む方法はありますか?doPost()
または、データベースからベースになっている永続エンティティをリロードして、メソッドで再作成することはできますか?Hibernateがエンティティをキャッシュする場合、新しい変更を永続化する前に、元のフォームオブジェクトを再作成するのはかなり速いはずです。#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つの欠点は、比較に含めたくない新しいインスタンス変数をフォームクラス(またはその親クラス)に追加することに注意する必要があることです。