2010-12-27 12 views
4

Doubleプロパティが、お金であることを示す@Moneyという制約があります。 ConstraintValidatorと書いて、@Moneyプロパティが有効な値を持っているかどうかを確認します。これはCurrencyインスタンスに依存します。たとえば、USDはドルとセントの両方の値を持ちますが、日本円はそうではありません。したがって、19.99はUSDの有効な値ですが、JPYの値はありません。 Currencyの値は、同じBeanの別のプロパティに格納されます。JSR-303:もう1つのクロスフィールド検証問題

問題は、ConstraintValidator内の特定のBeanのCurrencyプロパティを参照しています。私はそれをクラスレベルの検証にすることを考えましたが、クラスレベルでは、どのフィールドがお金であるかを書くのはかなり面倒で冗長でしょう。さらに重要なのは、複数のmoneyプロパティそれは無効です。

どんな提案も、Hibernate Validator固有のものであれば何でも構いません。

ありがとうございます!

答えて

3

IMOの場合、最も簡単な解決策は、情報、お金のタイプ(通貨)とお金の価値の両方を保持する別のJavaクラス、たとえばMoneyを作成することです。この後、制約を作成

public class Money { 

    private Currency currency; 
    private Double value; 

    public Currency getCurrency() { return currency; } 
    public void setCurrency(Currency currency) { this.currency = currency; } 

    public Double getValue() { return value; } 
    public void setValue(Double value) { this.value = value; } 

    public boolean isValid() { 
     if(getCurrency() == null || getValue() == null) { 
      return false; 
     } 

     // critical logic goes here 

     // sample code 
     if("JPY".equalsIgnoreCase(currency.getCurrencyCode())) { 
      int intValue = getValue().intValue(); 
      double diff = getValue() - intValue; 
      if(diff > 0) { 
       return false; 
      } 
     } 

     /*double fractionValue = value - (value % (currency.getDefaultFractionDigits() * 10)); 
     if(fractionValue > currency.getDefaultFractionDigits() * 10) { 
      return false; 
     }*/ 

     return true; 
    } 

} 

@ValidMoneyMoneyValidator言います。

public class MoneyValidator implements ConstraintValidator<ValidMoney, Money> { 

    @Override 
    public void initialize(ValidMoney constraintAnnotation) { 
     // TODO Auto-generated method stub 
    } 

    @Override 
    public boolean isValid(Money value, ConstraintValidatorContext context) { 
     return value.isValid(); 
    } 

} 

例: -

public class Bid { 
    @ValidMoney 
    private Money bidAmount;  
} 
+5

これ。また、金額にdoubleやfloatを使用しないでください。与えられたcurrencの最小金額を数えるlongを使用してください。 –

+0

私はこの解決法について実際には考えましたが、永続クラスで使用されるため、プリミティブ型に固執したいと考えました。あなたはいくつかのインターフェースを実装することによってHibernateにカスタムタイプを永続させることができますが、それが必要であるかどうかは確かではありません。それにもかかわらずありがとう。 –

+2

ところで、あなたは 'MoneyValidator'を取り除き、' Bid'クラスの '@ Valid'アノテーションと' Money.isValid() 'の' @ AssertTrue'で置き換えることができます。 –