2010-12-27 12 views
4

Ich habe eine @Money Einschränkung, die angibt, die annotierte Double Eigentum ist, nun, Geld. Ich schrieb eine ConstraintValidator, die überprüft, ob eine @Money Eigenschaft einen gültigen Wert hat, der von einer Currency Instanz abhängt. Zum Beispiel hat der USD sowohl Dollar- als auch Cent-Werte, während der japanische Yen dies nicht tut. Daher ist der 19,99 ein gültiger Wert für den USD, aber nicht für den JPY. Der Wert Currency wird in einer anderen Eigenschaft derselben Bean gespeichert.JSR-303: Noch ein weiteres Cross-Field-Validierungsproblem

Das Problem ist die Currency Eigenschaft einer bestimmten Bohne innerhalb der ConstraintValidator nachschlagen. Ich habe darüber nachgedacht, es auf Klassenebene zu validieren, aber es wäre ziemlich umständlich und überflüssig, auf Klassenebene zu schreiben, welche Felder Geld sind, und was noch wichtiger ist, Sie können nur eine Fehlermeldung generieren, selbst wenn es mehr als eine Geldeigenschaft gibt das ist ungültig.

Alle Vorschläge, auch Hibernate Validator spezifische sind willkommen.

Danke!

Antwort

3

IMO, ist die einfachste Lösung, eine separate Java-Klasse zu erstellen, sagen Money, die beide Informationen enthält, die Art des Geldes (d. H. Währung) und den Wert des Geldes.

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; 
    } 

} 

Danach, sagen eine Einschränkung erstellen @ValidMoney und MoneyValidator.

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(); 
    } 

} 

Beispiel: -

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

Dies. Verwenden Sie auch niemals Double oder Float für monetäre Werte, verwenden Sie ein long, das den kleinsten Nennwert für das gegebene Currenc zählt. –

+0

Ich dachte eigentlich über diese Lösung nach, wollte aber bei einem primitiven Typ bleiben, da er in persistenten Klassen verwendet wird. Sie können einen benutzerdefinierten Typ in Hibernate beibehalten, indem Sie einige wenige Schnittstellen implementieren, aber nicht sicher sind, ob dies erforderlich ist. Danke trotzdem. –

+2

BTW, Sie können wahrscheinlich 'MoneyValidator' loswerden und ersetzen Sie es durch' @ Valid' Annotation in 'Bid' Klasse und' @ AssertTrue' für 'Money.isValid()' –

Verwandte Themen