【问题标题】:JSR-303: Yet Another Cross-field Validation ProblemJSR-303:又一个跨领域验证问题
【发布时间】:2011-05-31 08:41:41
【问题描述】:

我有一个@Money 约束,它表明带注释的Double 属性是金钱。我写了一个ConstraintValidator 来检查@Money 属性是否具有有效值,这取决于Currency 实例。例如,美元同时具有美元和美分价值,而日元则没有,因此虽然 19.99 是美元的有效价值,但它不适用于日元。 Currency 值存储在同一个 bean 的另一个属性中。

问题是在ConstraintValidator 中查找给定bean 的Currency 属性。我想过做类级别的验证,但是在类级别写哪些字段是金钱会很麻烦和多余,更重要的是,即使有多个金钱属性,也只能生成一个错误消息这是无效的。

欢迎任何建议,甚至是特定于 Hibernate Validator 的建议。

谢谢!

【问题讨论】:

    标签: java hibernate-validator bean-validation


    【解决方案1】:

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

    【讨论】:

    • 这个。此外,切勿将双精度或浮点数用于货币值,使用计算给定货币最小面额的长整数。
    • 我实际上考虑过这个解决方案,但想坚持使用原始类型,因为它将用于持久类。您可以通过实现一些接口在 Hibernate 中保留自定义类型,但不确定是否有必要。不过还是谢谢。
    • 顺便说一句,你可能会摆脱 MoneyValidator 并将其替换为 Bid 类中的 @Valid 注释和 @AssertTrue 中的 Money.isValid() 注释
    猜你喜欢
    • 2011-10-23
    • 2015-01-10
    • 2011-10-30
    • 2018-08-15
    • 1970-01-01
    • 2021-11-06
    • 1970-01-01
    • 2018-08-24
    • 2011-06-09
    相关资源
    最近更新 更多