Spring Data JPA validation is missing on update (merge)
Asked Answered
M

0

3

I'm working on project with Spring boot 1.5.4.RELEASE with Spring Data JPA.

Stuck on issue that Hibernate validator isn't executed when updating entity or at least in some cases it doesn't validate.

For Person like below it is forbidden to have empty name and skills collection have to has min 1 element and max 5. Both of them are verified during call save on Spring Data repository. However for call save on already existing entity it will verify only constraints of name - and won't check skills.

@Entity
public class Person {
    @Id
    @GeneratedValue
    private Long id;

    @NotBlank
    private String name;

    @ElementCollection(fetch = FetchType.EAGER)
    @Size(min = 1, max = 5)
    private Set<String> skills = new HashSet<>();

    protected Person() {
    }

    public Person(final String name, final Collection<String> skills) {
    this.name = name;
    this.skills.addAll(skills);
    }

    public void updateSkills(Collection<String> skills) {
    this.skills.clear();
    this.skills.addAll(skills);
    }

    public void updateName(final String name) {
    this.name = name;
    }
    //getters
}

and when creating new entity with empty list of skills it will throw ConstraintValidationException as expected:

@Test(expected = ConstraintViolationException.class)
public void shouldFailWhenSkillsAreEmpty() {
    //given
    Person person = new Person("gucio", Collections.EMPTY_LIST);
    //when
    personRepository.save(person);
    //then
}

https://github.com/konczak/demo-skills-validation-issue/blob/master/src/test/java/com/example/demo/entity/PersonTest.java#L80

however when doing same - storing empty list on entity update (merge underhood? not sure) it will pass while I would expect exception:

@Test(expected = ConstraintViolationException.class)
public void shouldFailWhenUpdateSkillsToEmpty() {
    //given
    Person person = new Person("gucio", Arrays.asList(JAVA, SQL));
    person = personRepository.save(person);
    person.updateSkills(Collections.EMPTY_LIST);
    //when
    personRepository.save(person);
    //then
}

https://github.com/konczak/demo-skills-validation-issue/blob/master/src/test/java/com/example/demo/entity/PersonTest.java#L104

I have wrote test with manually created validator and validate such Person and as expected it returns 1 ConstraintViolation for field skills:

https://github.com/konczak/demo-skills-validation-issue/blob/master/src/test/java/com/example/demo/entity/PersonTest.java#L119

You can easily take a look into a sample project:

https://github.com/konczak/demo-skills-validation-issue

I understood that there is a difference under save method for transient and attached/detached entity but still I would expect validation for updating/merging. Again strange thing is that it will validate field name for blank value on update - it throws different exception but a original cause is ConstraingViolationException.

https://github.com/konczak/demo-skills-validation-issue/blob/master/src/test/java/com/example/demo/entity/PersonTest.java#L91

What am I missing or misunderstood in this case?

Marinamarinade answered 30/8, 2017 at 14:24 Comment(3)
Did you find a solution? I've the same problem!Crutcher
For me easiest solution was to inject instance of javax.validation.Validator (bean validator) to class performing save, execute validate method and check that result contains any errors.Kery
Actual issue lies in github.com/hibernate/hibernate-orm/blob/5.0.12/hibernate-core/src/main/java/org/hibernate/cfg/beanvalidation/BeanValidationEventListener.java :112 and event which is propagated. In case of changes over collection it is PreDeleteEvent which set operation group to DELETE. And for pre-remove validation isn't executed. In Spring boot I could set this spring.jpa.properties.javax.persistence.validation.group.pre-remove=javax.validation.groups.Default and in result on delete validation will be executed same as for insert and update but exception is TransactionSystemException.Kery

© 2022 - 2024 — McMap. All rights reserved.