Hibernate Validation Framework Tutorial – Using @NotNull, @Size, and More

Illustration for Hibernate Validation Framework Tutorial – Using @NotNull, @Size, and More
By Last updated:

Data integrity is one of the most critical aspects of any application. While databases enforce constraints like NOT NULL and UNIQUE, it’s often more efficient to catch invalid data before it reaches the database. This is where Hibernate Validator (the reference implementation of Jakarta Bean Validation) comes into play.

Think of Hibernate validation as a quality gatekeeper: it ensures that only valid data flows from your Java objects into the database.

In this tutorial, we’ll cover Hibernate’s validation framework, annotations like @NotNull, @Size, @Email, and how to integrate validation with Hibernate, Spring, and enterprise applications.


What is Hibernate Validator?

Hibernate Validator is the reference implementation of Jakarta Bean Validation (JSR 380 / JSR 349). It provides declarative constraints on Java objects, ensuring that invalid data never reaches persistence.

Key Benefits

  • Declarative annotations for validation.
  • Works with Hibernate ORM and standalone apps.
  • Integrates seamlessly with Spring and JPA.
  • Prevents invalid data at the object level before hitting the database.

Maven Dependency

Add Hibernate Validator to your project:

<dependency>
    <groupId>org.hibernate.validator</groupId>
    <artifactId>hibernate-validator</artifactId>
    <version>8.0.1.Final</version>
</dependency>

<dependency>
    <groupId>jakarta.validation</groupId>
    <artifactId>jakarta.validation-api</artifactId>
    <version>3.0.2</version>
</dependency>

<dependency>
    <groupId>org.glassfish</groupId>
    <artifactId>jakarta.el</artifactId>
    <version>4.0.2</version>
</dependency>

Common Validation Annotations

Annotation Purpose
@NotNull Field must not be null
@NotEmpty Field must not be empty (for Strings, Collections)
@NotBlank Field must contain non-whitespace text
@Size(min, max) Defines size constraints for Strings, arrays, or collections
@Min, @Max Defines numeric limits
@Email Validates proper email format
@Pattern Defines regex-based validation
@Past, @Future Validates date/time constraints

Example Entity with Validation

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 cannot be null")
    @Size(min = 2, max = 50, message = "Name must be between 2 and 50 characters")
    private String name;

    @NotBlank(message = "Email cannot be blank")
    @Email(message = "Email should be valid")
    private String email;

    @Min(value = 18, message = "Age must be at least 18")
    @Max(value = 100, message = "Age must not exceed 100")
    private int age;

    // getters and setters
}

Validating an Entity

Programmatic Validation

ValidatorFactory factory = Validation.buildDefaultValidatorFactory();
Validator validator = factory.getValidator();

User user = new User();
user.setName("A"); // too short
user.setEmail("invalid-email");
user.setAge(15);

Set<ConstraintViolation<User>> violations = validator.validate(user);
for (ConstraintViolation<User> violation : violations) {
    System.out.println(violation.getPropertyPath() + " " + violation.getMessage());
}

Output:

name Name must be between 2 and 50 characters
email Email should be valid
age Age must be at least 18

Integration with Hibernate ORM

When using Hibernate ORM, validation is automatically triggered before an entity is persisted or updated.

Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();

User user = new User();
user.setName("A");
user.setEmail("badEmail");
user.setAge(10);

session.persist(user); // Validation triggers before insert
tx.commit();

This will throw a ConstraintViolationException if validation fails.


Spring Integration

Spring Boot automatically integrates Hibernate Validator with JPA repositories.

Example

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

    @Autowired
    private UserRepository repository;

    @PostMapping
    public ResponseEntity<User> createUser(@Valid @RequestBody User user) {
        User saved = repository.save(user);
        return ResponseEntity.ok(saved);
    }
}

Here, @Valid ensures that incoming JSON is validated before persisting.


Common Pitfalls & Anti-Patterns

  1. Relying only on database constraints → Validation should happen before SQL execution.
  2. Overusing @NotNull on optional fields → Leads to unnecessary failures.
  3. Ignoring Custom Validation → Sometimes domain rules require custom validators.
  4. Mixing DTO and Entity Validation → Separate validation for request objects vs persistence objects.

Best Practices

  • Use validation annotations at the domain level (entities).
  • Combine with DTO validation for REST APIs.
  • Handle ConstraintViolationException with proper error responses.
  • Write custom validators for domain-specific rules.
  • Keep validation messages user-friendly.

📌 Hibernate Version Notes

Hibernate 5.x

  • Uses javax.validation namespace.
  • Integrated with Bean Validation 1.1/2.0.
  • Manual configuration often needed.

Hibernate 6.x

  • Migrated to jakarta.validation.
  • Better integration with Spring Boot 3.x.
  • Improved exception handling for constraint violations.
  • Enhanced support for custom validators.

Conclusion & Key Takeaways

  • Hibernate Validator enforces data integrity before persistence.
  • Common annotations like @NotNull, @Size, and @Email simplify validation.
  • Validation integrates seamlessly with Hibernate ORM and Spring.
  • Always separate entity validation from API request validation when needed.
  • Proper use of validation improves data quality and user experience.

FAQ: Expert-Level Questions

Q1: What’s the difference between Hibernate and JPA?
Hibernate is a JPA implementation with additional features like validation and caching.

Q2: How does Hibernate caching improve performance?
It reduces redundant database queries by storing entities in memory.

Q3: What are the drawbacks of eager fetching?
It loads unnecessary data, which can hurt performance.

Q4: How do I solve the N+1 select problem in Hibernate?
Use fetch joins, @BatchSize, or entity graphs.

Q5: Can I use Hibernate without Spring?
Yes, Hibernate Validator works standalone or integrated with plain Hibernate ORM.

Q6: What’s the best strategy for inheritance mapping?
Depends: SINGLE_TABLE for performance, JOINED for normalization, TABLE_PER_CLASS for isolation.

Q7: How does Hibernate handle composite keys?
By using @Embeddable with @EmbeddedId or @IdClass.

Q8: How is Hibernate 6 different from Hibernate 5?
Hibernate 6 uses jakarta.validation, improves integration with Spring Boot, and enhances custom validation support.

Q9: Is Hibernate suitable for microservices?
Yes, but in microservices, lightweight validation frameworks or DTO validation may be more common.

Q10: When should I not use Hibernate?
Avoid Hibernate when direct SQL control or extreme performance is required.