Introduction

When JPA auto-validates entities before persisting or updating, any violated Bean Validation constraint throws ConstraintViolationException. This happens at flush/commit time, not when the entity is created, making it harder to trace back to the root cause.

This error is common when entities have @NotNull, @Size, @Pattern, or custom validation constraints that are not satisfied by the incoming data.

Symptoms

  • Application throws "javax.validation.ConstraintViolationException" during entity persist or merge
  • Error shows which constraint failed: "must not be null", "size must be between 1 and 100"
  • Validation happens at transaction commit, not when setting the entity field

Common Causes

  • Required field (@NotNull) is null when the entity is persisted
  • String length exceeds @Size or @Pattern constraint limits
  • Custom validator logic rejects the entity state

Step-by-Step Fix

  1. 1.Identify the violated constraint from the exception: The exception contains details about what failed.
  2. 2.```java
  3. 3.try {
  4. 4.entityManager.persist(user);
  5. 5.entityManager.flush();
  6. 6.} catch (ConstraintViolationException e) {
  7. 7.for (ConstraintViolation<?> violation : e.getConstraintViolations()) {
  8. 8.System.err.printf("Field: %s, Value: %s, Message: %s%n",
  9. 9.violation.getPropertyPath(),
  10. 10.violation.getInvalidValue(),
  11. 11.violation.getMessage());
  12. 12.}
  13. 13.// Example output:
  14. 14.// Field: email, Value: null, Message: must not be null
  15. 15.// Field: username, Value: "ab", Message: size must be between 3 and 50
  16. 16.}
  17. 17.`
  18. 18.Validate before persisting using the Validator API: Catch validation errors early.
  19. 19.```java
  20. 20.import javax.validation.Validator;

@Autowired private Validator validator;

public User createUser(User user) { Set<ConstraintViolation<User>> violations = validator.validate(user); if (!violations.isEmpty()) { throw new IllegalArgumentException( violations.stream() .map(ConstraintViolation::getMessage) .collect(Collectors.joining(", ")) ); } return userRepository.save(user); } ```

  1. 1.Use validation groups for partial validation: Apply different constraints for create vs update.
  2. 2.```java
  3. 3.public interface OnCreate {}
  4. 4.public interface OnUpdate {}

public class User { @NotNull(groups = OnCreate.class) @Null(groups = OnUpdate.class) private Long id;

@NotBlank(groups = {OnCreate.class, OnUpdate.class}) private String email;

@Size(min = 3, max = 50, groups = OnCreate.class) private String username; }

// Validate with specific group: validator.validate(user, OnCreate.class); ```

Prevention

  • Validate entities at the service layer boundary, not at the persistence layer
  • Use Bean Validation in your REST controllers with @Valid on request bodies
  • Log validation violations with full property path and value for easier debugging
  • Use validation groups to differentiate between create, update, and partial update scenarios