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>
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
}
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");
}
}
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);
}
}
Example JSON Response:
{
"name": "Name cannot be blank",
"email": "Invalid email format",
"password": "Password must be at least 8 characters long"
}
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";
}
}
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>
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 {};
}
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).+$");
}
}
Use It
@StrongPassword
private String password;
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)