1. 简介
在之前的文章《Java Bean Validation 基础》中,我们学习了如何对各种 Java 类型应用基本的 javax.validation
校验规则。本文将重点介绍如何使用 javax.validation
对 BigDecimal
类型进行校验。
由于 @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.00
或 99.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.validation
对 BigDecimal
进行校验,并通过 @DecimalMin
、@DecimalMax
和 @Digits
注解实现对数值大小和格式的控制。
这些注解在金融系统、订单系统等对精度要求高的场景中非常实用,能有效防止输入非法数值,避免潜在的业务风险。
完整代码示例可参考 GitHub 仓库。