java - 不完全是 4 位数字长的年份的 JPA 年份验证抛出异常

标签 java spring jpa bean-validation

我想使用 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 {};
}

validator 类:

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

关于java - 不完全是 4 位数字长的年份的 JPA 年份验证抛出异常,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/61838470/

相关文章:

java - 同一实体上的 JPA OneToOne 和 OneToMany

java - BasicDataSource 的转换异常

java - Kafka 消费者配置/性能问题

java.util.zip.ZipException : duplicate entry after FireBase add

spring - Spring Session 如何在单个浏览器中支持多个 session ?

java - Eclipse (JBoss Developer Studio) 不自动构建 JPA 元模型类

java - 需要访问 setOnClickListener 方法中的变量

库中的 Spring PropertySourcesPlaceholderConfigurer

java - Spring 是一个光荣的工厂;这是可以接受的吗?

mysql - @Query 使用 or, and