DEV Community

Sadiul Hakim
Sadiul Hakim

Posted on

Hibernate Validation with Spring Boot

1. What is Hibernate Validation?

Hibernate Validator is the reference implementation of the Jakarta Bean Validation (formerly JSR-380, JSR-303) specification.

It allows you to automatically validate Java objects (usually DTOs or entities) by adding annotations like @NotNull, @Email, @Size, etc., on fields or methods.

Spring integrates Hibernate Validator seamlessly — it validates:

  • Request bodies (@RequestBody)
  • Form data (@ModelAttribute)
  • Path variables and query parameters (@Validated)

2. Why Use It and When?

Purpose When to Use
Input Validation When handling API requests or form submissions.
Data Integrity To ensure valid data reaches your persistence layer (DB).
Declarative and Centralized Rules You can define constraints at the entity or DTO level instead of repeating logic everywhere.
Error Prevention Prevents invalid data early before processing business logic.

When NOT to use:

  • When validation logic is complex or context-dependent — use custom validators or service logic instead.
  • For cross-field validation that requires multiple properties — consider a class-level constraint.

3. Common Hibernate Validation Annotations

Here’s a categorized overview of the most used annotations.

Basic Constraints

Annotation Description Example
@NotNull Field must not be null @NotNull private String name;
@NotEmpty Field must not be null or empty (for Strings/Collections) @NotEmpty private String username;
@NotBlank Field must not be null or contain only spaces @NotBlank private String firstName;
@Null Field must be null @Null private Long id;

Numeric Constraints

Annotation Description Example
@Min(value) Must be ≥ value @Min(18)
@Max(value) Must be ≤ value @Max(100)
@Positive Must be > 0 @Positive private int quantity;
@NegativeOrZero Must be ≤ 0 @NegativeOrZero private int balance;
@Digits(integer, fraction) Controls number format @Digits(integer = 5, fraction = 2)

String Constraints

Annotation Description Example
@Size(min, max) Limits string length or collection size @Size(min=3, max=20)
@Email Must be valid email @Email private String email;
@Pattern(regexp) Must match regex @Pattern(regexp="^[A-Z0-9._%+-]+@[A-Z0-9.-]+$")

Date/Time Constraints

Annotation Description
@Past – Must be a past date
@Future – Must be a future date
@PastOrPresent – Past or current
@FutureOrPresent – Future or current

Object & Custom Validation

Annotation Description
@Valid Cascade validation to nested objects
@Validated Enables validation on Spring method arguments or controller params
@Constraint(validatedBy=...) Custom validator

4. Integrating Hibernate Validator in Spring Boot

Dependencies

If you use Spring Boot Starter Web, Hibernate Validator is included automatically via:

<dependency>
  <groupId>org.springframework.boot</groupId>
  <artifactId>spring-boot-starter-validation</artifactId>
</dependency>
Enter fullscreen mode Exit fullscreen mode

Example: Entity or DTO

public class UserDto {

    @NotBlank(message = "Name cannot be blank")
    private String name;

    @Email(message = "Invalid email format")
    private String email;

    @Size(min = 8, message = "Password must be at least 8 characters long")
    private String password;

    @Min(value = 18, message = "Age must be 18 or older")
    private int age;

    // getters and setters
}
Enter fullscreen mode Exit fullscreen mode

5. Returning Validation Errors in REST APIs

Example: Controller

@RestController
@RequestMapping("/api/users")
public class UserController {

    @PostMapping
    public ResponseEntity<?> createUser(@Valid @RequestBody UserDto user) {
        // If validation passes, this method executes
        return ResponseEntity.ok("User created successfully");
    }
}
Enter fullscreen mode Exit fullscreen mode

Example: Handle Errors (Global Exception Handler)

Create a handler to customize the validation response:

@RestControllerAdvice
public class GlobalExceptionHandler {

    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Map<String, String>> handleValidationErrors(MethodArgumentNotValidException ex) {
        Map<String, String> errors = new HashMap<>();

        ex.getBindingResult().getFieldErrors()
                .forEach(error -> errors.put(error.getField(), error.getDefaultMessage()));

        return ResponseEntity.badRequest().body(errors);
    }
}
Enter fullscreen mode Exit fullscreen mode

Example JSON Response:

{
  "name": "Name cannot be blank",
  "email": "Invalid email format",
  "password": "Password must be at least 8 characters long"
}
Enter fullscreen mode Exit fullscreen mode

6. Handling Validation in Spring MVC (Thymeleaf)

For server-side rendered apps (forms):

Controller Example

@Controller
@RequestMapping("/users")
public class UserMvcController {

    @GetMapping("/new")
    public String showForm(Model model) {
        model.addAttribute("user", new UserDto());
        return "user-form";
    }

    @PostMapping
    public String submitForm(@Valid @ModelAttribute("user") UserDto user,
                             BindingResult result, Model model) {
        if (result.hasErrors()) {
            return "user-form"; // redisplay form with errors
        }
        model.addAttribute("success", "User created successfully");
        return "success";
    }
}
Enter fullscreen mode Exit fullscreen mode

Thymeleaf Form Example

<form th:action="@{/users}" th:object="${user}" method="post">
    <input type="text" th:field="*{name}" placeholder="Name"/>
    <div th:if="${#fields.hasErrors('name')}" th:errors="*{name}"></div>

    <input type="email" th:field="*{email}" placeholder="Email"/>
    <div th:if="${#fields.hasErrors('email')}" th:errors="*{email}"></div>

    <input type="password" th:field="*{password}" placeholder="Password"/>
    <div th:if="${#fields.hasErrors('password')}" th:errors="*{password}"></div>

    <button type="submit">Submit</button>
</form>
Enter fullscreen mode Exit fullscreen mode

7. Bonus — Custom Validation Example

Custom Annotation

@Documented
@Constraint(validatedBy = StrongPasswordValidator.class)
@Target({ ElementType.FIELD })
@Retention(RetentionPolicy.RUNTIME)
public @interface StrongPassword {
    String message() default "Password must contain uppercase, lowercase, and a number";
    Class<?>[] groups() default {};
    Class<? extends Payload>[] payload() default {};
}
Enter fullscreen mode Exit fullscreen mode

Validator Implementation

public class StrongPasswordValidator implements ConstraintValidator<StrongPassword, String> {
    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        if (value == null) return false;
        return value.matches("^(?=.*[a-z])(?=.*[A-Z])(?=.*\\d).+$");
    }
}
Enter fullscreen mode Exit fullscreen mode

Use It

@StrongPassword
private String password;
Enter fullscreen mode Exit fullscreen mode

Summary

Topic Key Takeaway
What Bean Validation framework (Hibernate Validator) integrated in Spring.
Why To ensure data integrity and reduce boilerplate checks.
How Use annotations like @NotNull, @Email, etc.
Error Handling Use @Valid, BindingResult, and @RestControllerAdvice for clean error messages.
Custom Rules Create custom @Constraint annotations with validators.

Top comments (0)