谁能帮我为什么我无法在春季靴子中保存带有自定义验证器的字段的对象?
场景: 首先,我必须通过自定义验证器验证字段(工作正常),然后将实体保存到数据库中(这会中断)。 我在IntelliJ IDE上使用Spring boots框架。该代码在github上。 https://github.com/mhussainshah1/customvalidation
我有客户实体
@Entity
public class Customer {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private long id;
@ContactInfo //Custom Validator
@NotNull
private String contactInfo;
// standard constructor, getters, setters
}
我有ContactInfoExpression实体
@Entity
public class ContactInfoExpression {
@Id
@Column(name="expression_type")
private String type;
private String pattern;
//standard constructor, getters, setters
}
我有ContactInfoExpressionRepository
和CustomerRepository
扩展了CrudRepository<T, Id>
我在application.properties文件中使用具有以下配置的H2内存数据库。可以将contactInfoType
属性设置为以下值之一:电子邮件,电话或网站
spring.h2.console.enabled=true
spring.h2.console.path=/h2
spring.jpa.hibernate.ddl-auto=create
spring.datasource.url=jdbc:h2:mem:testdb
spring.jpa.show-sql=true
contactInfoType=email
#contactInfoType=phone
#contactInfoType=website
自定义验证器
@Configuration
public class ContactInfoValidator implements ConstraintValidator<ContactInfo, String> {
private static final Logger LOG = LogManager.getLogger(ContactInfoValidator.class);
@Value("${contactInfoType}")
private String expressionType;
private String pattern;
@Autowired
private ContactInfoExpressionRepository contactInfoExpressionRepository;
@Override
public void initialize(ContactInfo contactInfo) {
if (StringUtils.isEmptyOrWhitespace(expressionType)) {
LOG.error("Contact info type missing!");
} else {
pattern = contactInfoExpressionRepository.findById(expressionType)
.map(ContactInfoExpression::getPattern).get();
}
}
@Override
public boolean isValid(String value, ConstraintValidatorContext context) {
if (!StringUtils.isEmptyOrWhitespace(pattern)) {
return Pattern.matches(pattern, value);
}
LOG.error("Contact info pattern missing!");
return false;
}
}
自定义约束注释
@Constraint(validatedBy = { ContactInfoValidator.class })
@Target({ METHOD, FIELD, ANNOTATION_TYPE, CONSTRUCTOR, PARAMETER })
@Retention(RetentionPolicy.RUNTIME)
public @interface ContactInfo {
String message() default "Invalid value";
Class<?>[] groups() default {};
Class<? extends Payload>[] payload() default {};
}
我使用DataLoader类加载数据
@Component
public class DataLoader implements CommandLineRunner {
@Autowired
ContactInfoExpressionRepository contactInfoExpressionRepository;
@Autowired
CustomerRepository customerRepository;
@Override
public void run(String... args) throws Exception {
String pattern = "[a-z0-9!#$%&*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?";
ContactInfoExpression email = new ContactInfoExpression("email", pattern);
contactInfoExpressionRepository.save(email);
pattern = "^([0-9]( |-)?)?(\\(?[0-9]{3}\\)?|[0-9]{3})( |-)?([0-9]{3}( |-)?[0-9]{4}|[a-zA-Z0-9]{7})$";
ContactInfoExpression phone = new ContactInfoExpression("phone", pattern);
contactInfoExpressionRepository.save(phone);
pattern = "^(http:\\/\\/www\\.|https:\\/\\/www\\.|http:\\/\\/|https:\\/\\/)?[a-z0-9]+([\\-\\.]{1}[a-z0-9]+)*\\.[a-z]{2,5}(:[0-9]{1,5})?(\\/.*)?$";
ContactInfoExpression website = new ContactInfoExpression("website", pattern);
contactInfoExpressionRepository.save(website);
Customer customer1 = new Customer("mhussainshah79@gmail.com");
customerRepository.save(customer1);// Error: can`t save
}
}
我无法保存具有自定义验证器字段的客户对象。我在运行时遇到以下错误
java.lang.IllegalStateException: Failed to execute CommandLineRunner
Caused by: org.springframework.transaction.TransactionSystemException: Could not commit JPA transaction; nested exception is javax.persistence.RollbackException: Error while committing the transaction
Caused by: javax.persistence.RollbackException: Error while committing the transaction
Caused by: javax.validation.ValidationException: HV000032: Unable to initialize com.example.customvalidation.ContactInfoValidator.
Caused by: java.lang.NullPointerException: null
at com.example.customvalidation.ContactInfoValidator.initialize(ContactInfoValidator.java:41) ~[classes/:na]
at com.example.customvalidation.ContactInfoValidator.initialize(ContactInfoValidator.java:18) ~[classes/:na]
答案 0 :(得分:1)
该问题的解决方案是在application.properties
文件中添加以下内容。
properties spring.jpa.properties.javax.persistence.validation.mode:none
参考: 如何避免在Spring Boot应用程序中进行双重验证,Sanjay Patel,2018年5月15日 https://www.naturalprogrammer.com/blog/16386/switch-off-jpa-validation-spring-boot