Tutorials Logic, IN +91 8092939553 info@tutorialslogic.com
FAQs Support
Navigation
Home About Us Contact Us Blogs FAQs
Tutorials
All Tutorials
Services
Academic Projects Resume Writing Interview Questions Website Development
Compiler Tutorials

Hibernate Validation

Bean Validation (Jakarta Validation)

Hibernate Validator is the reference implementation of Jakarta Bean Validation (formerly javax.validation). It allows you to declare constraints directly on entity fields using annotations. Spring Boot includes it automatically via spring-boot-starter-validation.

Common Validation Annotations on Entity
package com.example.model;

import jakarta.persistence.*;
import jakarta.validation.constraints.*;

@Entity
@Table(name = "users")
public class User {

    @Id @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @NotNull(message = "Name is required")
    @NotBlank(message = "Name cannot be blank")
    @Size(min = 2, max = 50, message = "Name must be between 2 and 50 characters")
    private String name;

    @NotNull(message = "Email is required")
    @Email(message = "Email must be a valid email address")
    @Column(unique = true)
    private String email;

    @NotNull(message = "Password is required")
    @Size(min = 8, message = "Password must be at least 8 characters")
    @Pattern(regexp = "^(?=.*[A-Z])(?=.*[0-9]).+$",
             message = "Password must contain at least one uppercase letter and one digit")
    private String password;

    @Min(value = 18, message = "Age must be at least 18")
    @Max(value = 120, message = "Age must be at most 120")
    private Integer age;

    @DecimalMin(value = "0.0", inclusive = false, message = "Salary must be positive")
    @DecimalMax(value = "999999.99", message = "Salary exceeds maximum")
    @Digits(integer = 6, fraction = 2, message = "Invalid salary format")
    private Double salary;

    @NotNull
    @Positive(message = "Score must be positive")
    private Integer score;

    @Past(message = "Birth date must be in the past")
    private java.time.LocalDate birthDate;

    @Future(message = "Expiry date must be in the future")
    private java.time.LocalDate expiryDate;

    @AssertTrue(message = "Terms must be accepted")
    private boolean termsAccepted;

    // getters/setters...
}

Custom Constraint Annotation

Custom Validation Constraint
package com.example.validation;

import jakarta.validation.Constraint;
import jakarta.validation.Payload;
import java.lang.annotation.*;

// Step 1: Define the annotation
@Documented
@Constraint(validatedBy = UsernameValidator.class) // Link to validator class
@Target({ElementType.FIELD, ElementType.PARAMETER})
@Retention(RetentionPolicy.RUNTIME)
public @interface ValidUsername {

    String message() default "Username must be 3-20 chars, alphanumeric and underscores only";

    Class<?>[] groups() default {};

    Class<? extends Payload>[] payload() default {};
}

// Usage on entity field:
// @ValidUsername
// private String username;
package com.example.validation;

import jakarta.validation.ConstraintValidator;
import jakarta.validation.ConstraintValidatorContext;

// Step 2: Implement the validator logic
public class UsernameValidator
        implements ConstraintValidator<ValidUsername, String> {

    private static final String USERNAME_PATTERN = "^[a-zA-Z0-9_]{3,20}$";

    @Override
    public void initialize(ValidUsername annotation) {
        // Called once before validation — can read annotation attributes here
    }

    @Override
    public boolean isValid(String value, ConstraintValidatorContext context) {
        if (value == null) return true; // Let @NotNull handle null check

        if (!value.matches(USERNAME_PATTERN)) {
            // Optionally customize the error message
            context.disableDefaultConstraintViolation();
            context.buildConstraintViolationWithTemplate(
                    "Username '" + value + "' is invalid. Use 3-20 alphanumeric chars.")
                   .addConstraintViolation();
            return false;
        }
        return true;
    }
}

@Valid in Spring MVC Controllers

@Valid in REST Controller with Error Handling
package com.example.controller;

import com.example.model.User;
import jakarta.validation.Valid;
import org.springframework.http.ResponseEntity;
import org.springframework.validation.BindingResult;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.MethodArgumentNotValidException;
import org.springframework.validation.FieldError;
import java.util.*;

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

    // @Valid triggers Bean Validation on the @RequestBody
    // If validation fails, Spring throws MethodArgumentNotValidException
    @PostMapping
    public ResponseEntity<User> createUser(@Valid @RequestBody User user) {
        // If we reach here, validation passed
        return ResponseEntity.status(201).body(userService.save(user));
    }

    // Global exception handler for validation errors
    @ExceptionHandler(MethodArgumentNotValidException.class)
    public ResponseEntity<Map<String, String>> handleValidationErrors(
            MethodArgumentNotValidException ex) {

        Map<String, String> errors = new LinkedHashMap<>();

        // Collect all field errors
        ex.getBindingResult().getAllErrors().forEach(error -> {
            String field   = ((FieldError) error).getField();
            String message = error.getDefaultMessage();
            errors.put(field, message);
        });

        return ResponseEntity.badRequest().body(errors);
    }
}

// Example error response for invalid input:
// {
//   "name": "Name must be between 2 and 50 characters",
//   "email": "Email must be a valid email address",
//   "age": "Age must be at least 18"
// }

Previous Next

Ready to Level Up Your Skills?

Explore 500+ free tutorials across 20+ languages and frameworks.