Java
UniqueConstraint
annotations
Hibernate
JPA

UniqueConstraint annotation in Java

Master System Design with Codemia

Enhance your system design skills with over 120 practice problems, detailed solutions, and hands-on exercises.

Introduction

In JPA, @UniqueConstraint is a schema-level mapping hint used with @Table to tell the database that one or more columns must be unique together. It is most useful for composite uniqueness rules such as “email must be unique” or “tenant id plus username must be unique as a pair.” The important point is that this is a database constraint, not just an application-side validation rule.

Basic Usage with @Table

@UniqueConstraint is declared inside the uniqueConstraints attribute of @Table.

java
1import jakarta.persistence.Entity;
2import jakarta.persistence.Id;
3import jakarta.persistence.Table;
4import jakarta.persistence.UniqueConstraint;
5
6@Entity
7@Table(
8    name = "users",
9    uniqueConstraints = {
10        @UniqueConstraint(name = "uk_users_email", columnNames = {"email"})
11    }
12)
13public class User {
14    @Id
15    private Long id;
16
17    private String email;
18}

This tells the persistence provider to create a database uniqueness rule for the email column when schema generation is enabled.

Composite Uniqueness

The annotation is especially useful when uniqueness involves more than one column.

java
1import jakarta.persistence.Entity;
2import jakarta.persistence.Id;
3import jakarta.persistence.Table;
4import jakarta.persistence.UniqueConstraint;
5
6@Entity
7@Table(
8    name = "memberships",
9    uniqueConstraints = {
10        @UniqueConstraint(
11            name = "uk_memberships_tenant_user",
12            columnNames = {"tenant_id", "username"}
13        )
14    }
15)
16public class Membership {
17    @Id
18    private Long id;
19
20    private String tenantId;
21    private String username;
22}

This allows the same username to exist in different tenants while preventing duplicates inside one tenant.

@UniqueConstraint vs @Column(unique = true)

For a single column, JPA also offers @Column(unique = true). That can be fine for a simple one-column uniqueness rule, but @UniqueConstraint is clearer when:

  • you need a composite key
  • you want to name the constraint explicitly
  • you want all table-level uniqueness rules visible in one place

In other words, @UniqueConstraint scales better as the schema grows more expressive.

What Happens at Runtime

The database enforces the uniqueness rule. If your application tries to insert a duplicate row, the write fails and the persistence layer raises an exception.

That means you should still validate user input at the application level for better error messages, but the database constraint remains the final guard against race conditions and bad concurrent writes.

Schema Generation Is a Separate Concern

The annotation only affects the generated schema if your environment actually lets JPA or Hibernate create or update the database schema. If the schema is managed through migrations such as Flyway or Liquibase, you should mirror the same unique constraint in those migrations too.

Do not assume the annotation alone changes an already-existing production database.

Constraint Violations Should Be Handled Deliberately

When the database rejects a duplicate value, users still need a useful application response. Catch the persistence-layer exception near your service boundary and translate it into a domain-specific error instead of leaking raw SQL details back to callers.

That does not weaken the database rule. It simply turns a low-level persistence failure into an application message that users and API clients can actually understand.

Common Pitfalls

  • Expecting @UniqueConstraint to behave like application-level validation only.
  • Using it on an existing schema without adding the matching migration.
  • Confusing one-column uniqueness with composite uniqueness needs.
  • Forgetting that duplicate inserts can still race unless the database constraint exists.
  • Leaving constraint names implicit and ending up with unreadable generated names in the database.

Summary

  • '@UniqueConstraint defines database-level uniqueness rules through JPA table metadata.'
  • Use it with @Table, especially for composite uniqueness.
  • It complements application validation but does not replace database enforcement.
  • '@Column(unique = true) is fine for simple one-column cases, but @UniqueConstraint is more explicit and flexible.'
  • Keep schema migrations and entity annotations aligned so the actual database matches the model.

Course illustration
Course illustration

All Rights Reserved.