java - 对于不完全为 4 位数的年份,JPA 年份验证抛出异常
问题描述
我想使用 JPA 在 Spring 应用程序中验证表单,但我在现场生产年份遇到问题。当我使用正好 4 位数字的年份时,验证成功,例如 2010。但是,当我输入小于 1000 或大于 9999 的表单值(非 4 位数字)时,我得到了这个异常:
Failed to convert property value of type java.lang.String to
required type java.time.Year for property productionYear;
nested exception is org.springframework.core.convert.ConversionFailedException:
Failed to convert from type [java.lang.String] to
type [@javax.persistence.Convert @javax.persistence.Column
@javax.validation.constraints.NotNull @com.kucharek.motorcycleshop.data.ProductionYearConstraint
java.time.Year] for value 12345;
nested exception is java.lang.IllegalArgumentException:
Parse attempt failed for value [12345]
该字段的 SQL 声明:
production_year year not null
check (production_year between
year("1885-01-01") and year(current_date())
)
实体类中的Java声明:
@Convert(converter = YearAttributeConverter.class)
@Column(name = "production_year")
@NotNull(message = "Production year is obligatory")
@ProductionYearConstraint(message = "Production year should be between 1885 and current year")
private Year productionYear;
转换器类:
@Converter(autoApply = true)
public class YearAttributeConverter
implements AttributeConverter<Year, Short> {
@Override
public Short convertToDatabaseColumn(Year attribute) {
return (short) attribute.getValue();
}
@Override
public Year convertToEntityAttribute(Short dbData) {
return Year.of(dbData);
}
}
验证注释:
@Constraint(validatedBy = ProductionYearValidator.class)
@Target(ElementType.FIELD)
@Retention(RetentionPolicy.RUNTIME)
public @interface ProductionYearConstraint {
String message() default "Invalid production year";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
验证器类:
public class ProductionYearValidator
implements ConstraintValidator<ProductionYearConstraint, Year> {
@Override
public boolean isValid(Year year, ConstraintValidatorContext context) {
return year != null && year.getValue() >= 1885 &&
year.getValue() < Year.now().getValue() ;
}
}
我做错了什么?我应该更改数据库或模型中的数据类型吗?如何处理异常并打印给用户我的自定义错误消息而不是打印堆栈跟踪?
解决方案
我已经用自定义消息文件解决了这个问题。
配置自定义消息文件messages.yml的配置类:
@Configuration
public class MessageSourceConfiguration {
@Bean
public MessageSource messageSource() throws IOException {
ResourceBundleMessageSource messageSource = new ResourceBundleMessageSource();
messageSource.setCommonMessages(yamlProperties());
return messageSource;
}
@Bean
public Properties yamlProperties() throws IOException {
YamlPropertiesFactoryBean bean = new YamlPropertiesFactoryBean();
bean.setResources(new ClassPathResource("messages.yml"));
return bean.getObject();
}
}
文件资源/messages.yml:
typeMismatch:
motorcycle:
productionYear: Production year should be number between 1885 and current year
推荐阅读
- wpf - 来自后面代码的 WPF 样式不适用
- javascript - 为什么单击我的动态创建的 html 会插入到最后一张循环卡上
- java - 为什么我会收到此错误 访问 stax 流时出错
- javascript - 从前端 fetch() 请求调用时,Express res.redirect() 不会重定向浏览器 URL
- java - 排除 JVM Jar 打开问题
- python - Python 中的 Adobe Acrobat API
- javascript - Laravel 5.6 - 使用 laravel-mix 拆分 vuejs 代码
- sql - 我可以使用 Pivot 或 Aggregation 并编写查询将多行转换为多列吗
- python - 如何在macos上更正图片tkinter messagebox tkinter
- python - 对于数据框,如何删除具有所有列的每一行等于无