1

私の Spring 4 駆動型ポートレットには、日付フィールドを含むデータ オブジェクトがあります。JSP ビューには、日付 (dd/mm/yyyy) と時刻 (hh/mm) という 2 つの個別のフィールドがあります。コントローラーのアクション ハンドラーは、@ModelAttribute-annotation を使用してフォーム データを受け取ります。

@ActionMapping(params = "action=update")
public void onUpdate(@Valid @ModelAttribute("myObject") MyObject myObject,
   BindingResult bindingResult, ActionResponse response, SessionStatus status)
{
   if (!bindingResult.hasErrors())
      myObjectService.save(myObject);
   else
      // provide 'myObject' in the view which displays validation errors
}

利用可能な日付全体に対してフィールドが1つしかないため、フォームデータが検証されてonUpdate()受信される前に、日付と時刻をマージする必要があります。myObjectMyObjectjava.util.Calendar

この必要性を回避するためのアイデア 1

MyObjectここで、日付を の 2 つの個別のフィールドに分割し、必要に応じて値をマージするゲッターを提供することもできると考えました。

@Column(name = "begin")
public Calendar getBegin()
{
   // return calendar object built from this.beginDate and this.beginTime
}

しかし、これはいくつかの理由で良い考えではないと思います (この質問を参照してください: Hibernate Annotations - which is better, field or property access? ) モデルオブジェクトをデータベースレコードのミラーにしたいので、そうする必要があります割り当てられる前に検証されます。

アイデア2

myObject別のアプローチは、日付または時刻を設定するときに、オンデマンドでカレンダー オブジェクトを作成または変更することです。

@Column(name = "begin")
@Temporal(TemporalType.TIMESTAMP)
private Calendar begin;

public void setBeginDate(String value)
{
    // assign a new calendar object to "begin", if "begin" is null
    // set only day, month and year components on this calendar object
}

public void setBeginTime(String value)
{
    // see "setBeginDate", do the same with hours and minutes
}

ここでの問題は、フィールド「日付」または「時刻」の 1 つだけが有効な場合に、新しいカレンダー オブジェクトが作成されることです。ビューのフィールドには、現在の日付または現在の時刻が入力されます (どちらの値が正しかったかによって異なります)。

isValidDateモデルに別のプライベート フラグを追加することで、この問題を解決することもできます。しかし、これは不潔な解決策だと思います。

結論

myObjectコントローラー用とmyObject実際のモデルオブジェクトとしては大きな違いがあると思います。myObject検証されて「マッピング」されるとすぐに、モデルオブジェクトになる必要があります。

だからここに私の質問:

  • @ModelAttribute最後のポイントは、一般的に悪い考えとして使用することを明らかにしていると思いますか?
  • または、インスタンスが作成される前にフォームデータをマッピングして検証する方法はありMyObjectますか?
  • そうでない場合、どのように問題を解決することをお勧めしますか?
4

1 に答える 1

0

EDIT :@initBinder逆でも構いません (1 フィールド -> N 属性)

フレームワークが、バインド配管に入ることなく、箱から出してあなたが望むこと (N フィールド -> 1 属性) を実行できるかどうかはわかりません。

この問題を回避するための 2 つの簡単な解決策を次に示します。

  • 古い「Struts」の方法でそれをMyObjectForm行い、ビューでのみ使用するオブジェクトを作成し、コントローラーでそれを に変換しますMyObject。技術的に健全な@Validサービスレイヤーで引き続き使用できます。MyObjectService

  • 数十の属性が含まれていない場合は、 + Controller レイヤーの検証をMyObject忘れて、各フィールドに使用するだけです。サービス層の検証はまだ進行中です。@ModelAttribute@RequestParam

Spring MVCの内部機能を使用して、フォームデータをオブジェクトに手動で「バインド」できるようにすることは確かにハックできますが、最終的には、配管がはるかに混乱する、私の2番目のポイントのようなものになります。

于 2014-04-07T09:35:18.777 に答える