1. 简介

在之前的文章《Java Bean Validation 基础》中,我们学习了如何对各种 Java 类型应用基本的 javax.validation 校验规则。本文将重点介绍如何使用 javax.validationBigDecimal 类型进行校验。

由于 @Min@Max 注解只支持 long 类型的参数,**无法直接用于精度更高的 BigDecimal**,因此我们需要使用专门为 BigDecimal 设计的注解,包括:

  • @DecimalMin
  • @DecimalMax
  • @Digits

BigDecimal 是金融计算的首选类型,因为它提供了更高的精度和可控的舍入行为 ✅

接下来我们以一个 Invoice 类为例,展示这些注解的使用方式。

2. 校验 BigDecimal 实例

示例类定义

public class Invoice {

    @DecimalMin(value = "0.0", inclusive = false)
    @Digits(integer = 3, fraction = 2)
    private BigDecimal price;
    private String description;

    public Invoice(BigDecimal price, String description) {
        this.price = price;
        this.description = description;
    }
}

2.1 @DecimalMin

作用:确保字段值大于等于指定的最小值(支持字符串形式的数值)
该注解支持设置 inclusive 属性,表示是否包含等于的情况。

示例:

@DecimalMin(value = "0.0", inclusive = false)

表示 price 必须大于 0.0,不能等于 0.0 ❌

2.2 @DecimalMax

@DecimalMin 相对,用于限制字段值不超过指定最大值
同样支持 inclusive 参数,控制是否允许等于最大值。

例如:

@DecimalMax(value = "1000.00", inclusive = true)

表示允许的最大值是 1000.00 ✅

2.3 @Digits

用于限制数字的整数位数小数位数
该注解有两个参数:

  • integer:允许的最大整数位数
  • fraction:允许的最大小数位数

比如:

@Digits(integer = 3, fraction = 2)

表示最多允许 3 位整数 + 2 位小数,如 999.99 合法,1000.0099.999 都非法 ❌

⚠️ 注意:@Digits 是对格式的限制,不涉及数值大小比较。即使数值在范围内,但格式不符合也会校验失败。

2.4 测试用例

我们使用 javax.validation.Validator 来验证 Invoice 对象的校验规则。

整数位超过限制

@Test
public void whenMoreThanThreeIntegerDigits_thenShouldGiveConstraintViolations() {
    Invoice invoice = new Invoice(new BigDecimal("1021.21"), "Book purchased");
    Set<ConstraintViolation<Invoice>> violations = validator.validate(invoice);
    assertThat(violations).hasSize(1);
    assertThat(violations)
        .extracting("message")
        .containsOnly("numeric value out of bounds (<3 digits>.<2 digits> expected)");
}

整数位合法

@Test
public void whenLessThanThreeIntegerDigits_thenShouldNotGiveConstraintViolations() {
    Invoice invoice = new Invoice(new BigDecimal("10.21"), "Book purchased");
    Set<ConstraintViolation<Invoice>> violations = validator.validate(invoice);
    assertThat(violations).isEmpty();
}

小数位合法

@Test
public void whenTwoFractionDigits_thenShouldNotGiveConstraintViolations() {
    Invoice invoice = new Invoice(new BigDecimal("99.99"), "Book purchased");
    Set<ConstraintViolation<Invoice>> violations = validator.validate(invoice);
    assertThat(violations).isEmpty();
}

小数位超过限制

@Test
public void whenMoreThanTwoFractionDigits_thenShouldGiveConstraintViolations() {
    Invoice invoice = new Invoice(new BigDecimal("99.999"), "Book purchased");
    Set<ConstraintViolation<Invoice>> violations = validator.validate(invoice);
    assertThat(violations).hasSize(1);
    assertThat(violations)
        .extracting("message")
        .containsOnly("numeric value out of bounds (<3 digits>.<2 digits> expected)");
}

等于最小值(不允许)

@Test
public void whenPriceIsZero_thenShouldGiveConstraintViolations() {
    Invoice invoice = new Invoice(new BigDecimal("0.00"), "Book purchased");
    Set<ConstraintViolation<Invoice>> violations = validator.validate(invoice);
    assertThat(violations).hasSize(1);
    assertThat(violations)
        .extracting("message")
        .containsOnly("must be greater than 0.0");
}

大于最小值(合法)

@Test
public void whenPriceIsGreaterThanZero_thenShouldNotGiveConstraintViolations() {
    Invoice invoice = new Invoice(new BigDecimal("100.50"), "Book purchased");
    Set<ConstraintViolation<Invoice>> violations = validator.validate(invoice);
    assertThat(violations).isEmpty();
}

3. 总结

本文介绍了如何使用 javax.validationBigDecimal 进行校验,并通过 @DecimalMin@DecimalMax@Digits 注解实现对数值大小和格式的控制。

这些注解在金融系统、订单系统等对精度要求高的场景中非常实用,能有效防止输入非法数值,避免潜在的业务风险。

完整代码示例可参考 GitHub 仓库


原始标题:Javax BigDecimal Validation