SpringBoot doesn't handle org.hibernate.exception.ConstraintViolationException
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.
Introduction
When a database constraint is violated in a Spring Boot application, developers often expect to catch org.hibernate.exception.ConstraintViolationException directly and return a clean error response. In practice, that exception is often wrapped, translated, or even thrown later than expected during transaction commit. The fix is usually to catch the Spring-layer exception, understand when the flush happens, and distinguish Hibernate's exception from bean-validation exceptions with the same short name.
Know Which ConstraintViolationException You Are Seeing
There are two similarly named exceptions that cause a lot of confusion.
org.hibernate.exception.ConstraintViolationException comes from the persistence layer and usually means the database rejected an insert or update because of a unique key, foreign key, or not-null rule.
jakarta.validation.ConstraintViolationException comes from bean validation and happens before the SQL is even accepted by the database.
In a typical Spring Data JPA stack, the Hibernate exception is often translated into Spring's DataIntegrityViolationException. That is usually the exception you should handle in controllers or service boundaries.
Why Spring Boot Seems Not To Handle It
The most common reason is timing. JPA may delay the actual SQL until flush() or transaction commit. If you call repository.save(entity) inside a @Transactional method, the exception may not be thrown until the method is returning.
That means a local try block around save may not catch anything, because the database round trip has not happened yet.
A second reason is exception translation. If the call goes through a Spring-managed repository, the original Hibernate exception is commonly wrapped in DataIntegrityViolationException.
Catch The Spring Exception At The Right Layer
A common pattern is to force the SQL to execute with saveAndFlush, then catch DataIntegrityViolationException in a @RestControllerAdvice.
This keeps the HTTP response logic in one place and aligns with Spring's exception translation.
Unwrapping The Root Cause When You Need Details
Sometimes you need to inspect the cause chain to determine whether the conflict came from a unique constraint, foreign key, or another persistence issue.
This lets you keep Spring's translated exception as the entry point while still inspecting the underlying Hibernate cause when necessary.
Push Validation Earlier When Possible
If the rule is part of your domain model, validate it before the database call. For example, use bean validation for required fields and format checks. Database constraints still matter for safety, but pre-validation improves the error message and avoids treating every bad request as a persistence problem.
For uniqueness, application-level checks can improve user feedback, but they do not replace the database constraint because concurrent requests can still race. The database should remain the final authority.
Common Pitfalls
The biggest pitfall is catching the wrong exception type. If Spring translates the persistence exception, a handler for only Hibernate's exception may never run.
Another common issue is using save and expecting the exception immediately. If you need deterministic timing, use flush or saveAndFlush inside the transaction.
It is also easy to confuse bean validation failures with database constraint violations because both use the name ConstraintViolationException. Check the package name before deciding how to handle it.
Finally, avoid leaking raw database error messages back to clients. Constraint names often expose internal schema details that do not belong in public API responses.
Summary
- Spring often translates Hibernate's
ConstraintViolationExceptionintoDataIntegrityViolationException. - The exception may appear at
flush()or transaction commit, not atsave(). - Catch translated exceptions in a controller advice or service boundary.
- Distinguish database constraint failures from bean-validation failures with the same short name.
- Use database constraints for correctness and application validation for better user-facing errors.
Related reading
- SpringBoot error Registered driver with driverClassNameoracle.jdbc.driver.OracleDriver was not found, trying direct instantiation
- Springboot org.hibernate.MappingException Could not get constructor for org.hibernate.persister.entity.SingleTableEntityPersister
- SQL - Update multiple records in one query
- SQL based data diff longest common subsequence
- springboot How to exclude configuration class in dependency dependency
- Springboot How to use WebClient instead of RestTemplate for Performing Non blocking and Asynchronous calls
- SQL command to display history of queries
- SQL connection throws error when adding DistributedSession, SessionMiddleware

System Design Fundamentals
Build a strong foundation in designing scalable, reliable distributed systems.
View the courseTrack what you have practised
A free account saves your progress, solutions and study plan across every problem on Codemia.
System Design practice on Codemia
Work through 120+ system design problems with detailed solutions, from rate limiters to multi-region storage.