【发布时间】:2019-10-01 11:44:29
【问题描述】:
我尝试手动验证实体图。使用 Hibernate SessionFactory 时我没有遇到问题。由于我切换到 Hibernate JPA,因此不再验证嵌套实体。为什么?
- Hibernate event-based validation 使用默认组运行,并在 pre-persiste/pre-update/pre-remove 阶段工作,但手动验证不会检测嵌套实体中的验证错误。
- 整个实体图都被急切地加载,所以我认为TraversableResolver 不是这里的问题。无论如何,我仍然声明了一个始终请求导航到嵌套实体的自定义 TraversableResolver。
- 如果我在单元测试中创建一个新的实体图,在持久性上下文之外,就会发现验证错误。然而,如果我将父实体从持久性上下文中分离出来,仍然找不到验证错误。
任何理解这个问题的帮助将不胜感激。
我正在使用org.springframework.boot:spring-boot-starter-data-jpa(Spring Boot 2.1.7.RELEASE),与Hibernate 5.3.10.Final 打包在一起。我也在使用 Lombok。
这是我的代码。如果父类上存在alwaysAnError 字段,则会发现验证错误。如果此字段嵌套在 @Valid 子项中,则不会发现错误。
Parent.java
@Data @Builder @NoArgsConstructor @AllArgsConstructor
@Entity
@Table(name = "parent")
public class Parent {
[...]
@Valid
@Builder.Default
@OneToMany(mappedBy = "file", fetch = FetchType.EAGER, cascade = CascadeType.ALL, orphanRemoval = true)
@Fetch(value = FetchMode.SUBSELECT)
private List<@Valid Child> children = new ArrayList<>();
}
Child.java
@Data @Builder @NoArgsConstructor @AllArgsConstructor
@Entity
@Table(name = "child")
public class Child {
[...]
@ManyToOne
@JoinColumn(name = "file_id")
private File file;
@NotNull
@Transient
private String alwaysAnError = null;
}
ValidationService.java
Validator validator = Validation.byDefaultProvider()
.configure()
.traversableResolver(new TraversableResolver() {
@Override
public boolean isReachable(Object traversableObject, Path.Node traversableProperty, Class<?> rootBeanType, Path pathToTraversableObject, ElementType elementType) {
return true;
}
@Override
public boolean isCascadable(Object traversableObject, Path.Node traversableProperty, Class<?> rootBeanType, Path pathToTraversableObject, ElementType elementType) {
return true;
}
})
.buildValidatorFactory()
.getValidator();
Set<ConstraintViolation<Declaration>> constraintViolations = validator.validate(fileInstance, Default.class);
if (!constraintViolations.isEmpty()) {
throw new RuntimeException(constraintViolations);
}
相关问题:
【问题讨论】:
标签: java hibernate spring-boot jpa spring-data-jpa