Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

Partner – Microsoft – NPI EA (cat = Baeldung)
announcement - icon

Azure Container Apps is a fully managed serverless container service that enables you to build and deploy modern, cloud-native Java applications and microservices at scale. It offers a simplified developer experience while providing the flexibility and portability of containers.

Of course, Azure Container Apps has really solid support for our ecosystem, from a number of build options, managed Java components, native metrics, dynamic logger, and quite a bit more.

To learn more about Java features on Azure Container Apps, visit the documentation page.

You can also ask questions and leave feedback on the Azure Container Apps GitHub page.

Partner – Microsoft – NPI EA (cat= Spring Boot)
announcement - icon

Azure Container Apps is a fully managed serverless container service that enables you to build and deploy modern, cloud-native Java applications and microservices at scale. It offers a simplified developer experience while providing the flexibility and portability of containers.

Of course, Azure Container Apps has really solid support for our ecosystem, from a number of build options, managed Java components, native metrics, dynamic logger, and quite a bit more.

To learn more about Java features on Azure Container Apps, you can get started over on the documentation page.

And, you can also ask questions and leave feedback on the Azure Container Apps GitHub page.

Partner – Orkes – NPI EA (cat=Spring)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

Partner – Orkes – NPI EA (tag=Microservices)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

eBook – Guide Spring Cloud – NPI EA (cat=Spring Cloud)
announcement - icon

Let's get started with a Microservice Architecture with Spring Cloud:

>> Join Pro and download the eBook

eBook – Mockito – NPI EA (tag = Mockito)
announcement - icon

Mocking is an essential part of unit testing, and the Mockito library makes it easy to write clean and intuitive unit tests for your Java code.

Get started with mocking and improve your application tests using our Mockito guide:

Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Reactive – NPI EA (cat=Reactive)
announcement - icon

Spring 5 added support for reactive programming with the Spring WebFlux module, which has been improved upon ever since. Get started with the Reactor project basics and reactive programming in Spring Boot:

>> Join Pro and download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Jackson – NPI EA (cat=Jackson)
announcement - icon

Do JSON right with Jackson

Download the E-book

eBook – HTTP Client – NPI EA (cat=Http Client-Side)
announcement - icon

Get the most out of the Apache HTTP Client

Download the E-book

eBook – Maven – NPI EA (cat = Maven)
announcement - icon

Get Started with Apache Maven:

Download the E-book

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

eBook – RwS – NPI EA (cat=Spring MVC)
announcement - icon

Building a REST API with Spring?

Download the E-book

Course – LS – NPI EA (cat=Jackson)
announcement - icon

Get started with Spring and Spring Boot, through the Learn Spring course:

>> LEARN SPRING
Course – RWSB – NPI EA (cat=REST)
announcement - icon

Explore Spring Boot 3 and Spring 6 in-depth through building a full REST API with the framework:

>> The New “REST With Spring Boot”

Course – LSS – NPI EA (cat=Spring Security)
announcement - icon

Yes, Spring Security can be complex, from the more advanced functionality within the Core to the deep OAuth support in the framework.

I built the security material as two full courses - Core and OAuth, to get practical with these more complex scenarios. We explore when and how to use each feature and code through it on the backing project.

You can explore the course here:

>> Learn Spring Security

Course – All Access – NPI EA (cat= Spring)
announcement - icon

All Access is finally out, with all of my Spring courses. Learn JUnit is out as well, and Learn Maven is coming fast. And, of course, quite a bit more affordable. Finally.

>> GET THE COURSE
Course – LSD – NPI EA (tag=Spring Data JPA)
announcement - icon

Spring Data JPA is a great way to handle the complexity of JPA with the powerful simplicity of Spring Boot.

Get started with Spring Data JPA through the guided reference course:

>> CHECK OUT THE COURSE

Partner – LambdaTest – NPI EA (cat=Testing)
announcement - icon

End-to-end testing is a very useful method to make sure that your application works as intended. This highlights issues in the overall functionality of the software, that the unit and integration test stages may miss.

Playwright is an easy-to-use, but powerful tool that automates end-to-end testing, and supports all modern browsers and platforms.

When coupled with LambdaTest (an AI-powered cloud-based test execution platform) it can be further scaled to run the Playwright scripts in parallel across 3000+ browser and device combinations:

>> Automated End-to-End Testing With Playwright

Course – Spring Sale 2025 – NPI EA (cat= Baeldung)
announcement - icon

Yes, we're now running our Spring Sale. All Courses are 25% off until 26th May, 2025:

>> EXPLORE ACCESS NOW

Course – Spring Sale 2025 – NPI (cat=Baeldung)
announcement - icon

Yes, we're now running our Spring Sale. All Courses are 25% off until 26th May, 2025:

>> EXPLORE ACCESS NOW

1. Introduction

In this tutorial, we’ll discuss defining unique constraints using JPA and Hibernate.

First, we’ll explore unique constraints and how they differ from primary key constraints.

Then we’ll take a look at JPA’s important annotations, @Column(unique=true) and @UniqueConstraint. We’ll implement them to define the unique constraints on a single column and multiple columns.

Finally, we’ll learn how to define unique constraints on referenced table columns.

2. Unique Constraints

Let’s start with a quick recap. A unique key is a set of single or multiple columns of a table that uniquely identify a record in a database table.

Both the unique and primary key constraints provide a guarantee for uniqueness for a column or set of columns.

2.1. How It’s Different From Primary Key Constraints?

Unique constraints ensure that the data in a column or combination of columns is unique for each row. A table’s primary key, for example, functions as an implicit unique constraint. Hence, the primary key constraint automatically has a unique constraint.

Furthermore, we can have only one primary key constraint per table. However, there can be multiple unique constraints per table.
Simply put, the unique constraints apply in addition to any constraint entailed by primary key mapping.

The unique constraints we define are used during table creation to generate the proper database constraints, and may also be used at runtime to order insert, update, or delete statements.

2.2. What Are Single-Column and Multiple-Column Constraints?

A unique constraint can be either a column constraint or a table constraint. At the table level, we can define unique constraints across multiple columns.

JPA allows us to define unique constraints in our code using @Column(unique=true) and @UniqueConstraint. These annotations are interpreted by the schema generation process, creating constraints automatically.

Before anything else, we should emphasize that column-level constraints apply to a single column, and table-level constraints apply to the whole table.

We’ll discuss this in more detail in the next sections.

3. Set Up an Entity

An entity in JPA represents a table stored in a database. Every instance of an entity represents a row in the table.

Let’s start by creating a domain entity and mapping it to a database table. For this example, we’ll create a Person entity:

@Entity
@Table
public class Person implements Serializable {
    @Id
    @GeneratedValue
    private Long id;  
    private String name;
    private String password;
    private String email;
    private Long personNumber;
    private Boolean isActive;
    private String securityNumber;
    private String departmentCode;
    @JoinColumn(name = "addressId", referencedColumnName = "id")
    private Address address;
   //getters and setters
 }

An address field is a referenced field from the Address entity:

@Entity
@Table
public class Address implements Serializable {
    @Id
    @GeneratedValue
    private Long id;
    private String streetAddress;
    //getters and setters
}

Throughout this tutorial, we’ll use this Person entity to demonstrate our examples.

4. Column Constraints

When we have our model ready, we can implement our first unique constraint.

Let’s consider our Person entity that holds the person’s information. We have a primary key for the id column. This entity also holds the PersonNumber, which doesn’t contain any duplicate value. In addition, we can’t define the primary key because our table already has it.

In this case, we can use column unique constraints to make sure that no duplicate values are entered in a PersonNumber field. JPA allows us to achieve this using the @Column annotation with the unique attribute.

In the following sections, we’ll take a look at the @Column annotation, and then learn how to implement it.

4.1. @Column(unique=true)

The annotation type Column is used to specify the mapped column for a persistent property or field.

Let’s take a look at the definition:

@Target(value={METHOD,FIELD})
@Retention(value=RUNTIME)
public @interface Column {
    boolean unique;
   //other elements
 }

The unique attribute specifies whether the column is a unique key. This is a shortcut for the UniqueConstraint annotation, and is useful when the unique key constraint corresponds to only a single column.

We’ll see how to define it in the next section.

4.2. Defining the Column Constraints

Whenever the unique constraint is based only on one field, we can use @Column(unique=true) on that column.

Let’s define a unique constraint on the personNumber field:

@Column(unique=true)
private Long personNumber;

When we execute the schema creation process, we can validate it from the logs:

[main] DEBUG org.hibernate.SQL -
    alter table Person add constraint UK_d44q5lfa9xx370jv2k7tsgsqt unique (personNumber)

Similarly, if we want to restrict a Person to register with a unique email, we can add a unique constraint on the email field:

@Column(unique=true)
private String email;

Let’s execute the schema creation process and check the constraints:

[main] DEBUG org.hibernate.SQL -
    alter table Person add constraint UK_585qcyc8qh7bg1fwgm1pj4fus unique (email)

Although this is useful when we want to put a unique constraint on a single column, sometimes we may want to add unique constraints on a composite key, which is a combination of columns. To define a composite unique key, we can use table constraints. We’ll discuss that in the next section.

5. Table Constraints

A composite unique key is a unique key made up of a combination of columns. To define a composite unique key, we can add constraints on the table instead of a column. JPA helps us achieve this using the @UniqueConstraint annotation.

5.1. @UniqueConstraint Annotation

Annotation type UniqueConstraint specifies that a unique constraint is to be included in the generated DDL (Data Definition Language) for a table.

Let’s take a look at the definition:

@Target(value={})
@Retention(value=RUNTIME)
public @interface UniqueConstraint {
    String name() default "";
    String[] columnNames();
}

As we can see, the name and columnNames of type String and String[], respectively, are the annotation elements that may be specified for the UniqueConstraint annotation.

We’ll take a better look at each of the parameters in the next section, going through examples.

5.2. Defining Unique Constraints

Let’s consider our Person entity. A Person shouldn’t have any duplicate record for the active status. In other words, there won’t be any duplicate values for the key comprising personNumber and isActive. Here, we need to add unique constraints that span across multiple columns.

JPA helps us achieve this with the @UniqueConstraint annotation. We use it in the @Table annotation under the uniqueConstraints attribute. Let’s remember to specify the names of the columns:

@Table(uniqueConstraints = { @UniqueConstraint(columnNames = { "personNumber", "isActive" }) })

We can validate it once the schema is generated:

[main] DEBUG org.hibernate.SQL -
    alter table Person add constraint UK5e0bv5arhh7jjhsls27bmqp4a unique (personNumber, isActive)

One point to note here is that if we don’t specify a name, it’s a provider-generated value. Since JPA 2.0, we can provide a name for our unique constraint:

@Table(uniqueConstraints = { @UniqueConstraint(name = "UniqueNumberAndStatus", columnNames = { "personNumber", "isActive" }) })

And we can validate the same:

[main] DEBUG org.hibernate.SQL -
    alter table Person add constraint UniqueNumberAndStatus unique (personNumber, isActive)

Here we added unique constraints on a set of columns. We can also add multiple unique constraints, meaning unique constraints on multiple sets of columns. We’ll do just that in the next section.

5.3. Multiple Unique Constraints on a Single Entity

A table can have multiple unique constraints. In the last section, we defined unique constraints on a composite key: personNumber and isActive status. In this section, we’ll add constraints on the combination of securityNumber and departmentCode.

Let’s collect our unique indexes and specify them at once. We do this by repeating the @UniqueConstraint annotation in braces and separated by a comma:

@Table(uniqueConstraints = {
   @UniqueConstraint(name = "UniqueNumberAndStatus", columnNames = {"personNumber", "isActive"}),
   @UniqueConstraint(name = "UniqueSecurityAndDepartment", columnNames = {"securityNumber", "departmentCode"})})

Now let’s see the logs, and check the constraints:

[main] DEBUG org.hibernate.SQL -
    alter table Person add constraint UniqueNumberAndStatus unique (personNumber, isActive)
[main] DEBUG org.hibernate.SQL -
   alter table Person add constraint UniqueSecurityAndDepartment unique (securityNumber, departmentCode)

Up until now, we defined unique constraints on the fields in the same entity. However, in some cases, we may have referenced fields from other entities and need to ensure the uniqueness of those fields. We’ll discuss that in the next section.

6. Unique Constraints on a Referenced Table Column

When we create two or more tables that are related to each other, they’re often related by a column in one table referencing the primary key of the other table. That column is called the “foreign key.” For example, the Person and Address entities are connected through the addressId field. Hence, addressId acts as a referenced table column.

We can define unique constraints on the referenced columns. We’ll first implement it on a single column, and then on multiple columns.

6.1. Single-Column Constraints

In our Person entity, we have an address field that refers to the Address entity. A person should have a unique address.

So let’s define a unique constraint on the address field of the Person:

@Column(unique = true)
private Address address;

Now let’s quickly check this constraint:

[main] DEBUG org.hibernate.SQL -
   alter table Person add constraint UK_7xo3hsusabfaw1373oox9uqoe unique (address)

We can also define multiple column constraints on the referenced table column, as we’ll see in the next section.

6.2. Multiple-Column Constraints

We can specify unique constraints on a combination of columns. As stated earlier, we can use table constraints to do so.

Let’s define unique constraints on the personNumber and address, and add it to the uniqueConstraints array:

@Entity
@Table(uniqueConstraints = 
  { //other constraints
  @UniqueConstraint(name = "UniqueNumberAndAddress", columnNames = { "personNumber", "address" })})

Finally, let’s see the unique constraints:

[main] DEBUG org.hibernate.SQL -
    alter table Person add constraint UniqueNumberAndAddress unique (personNumber, address)

7. Conclusion

The unique constraints prevent two records from having identical values in a column or set of columns.

In this article, we learned how to define unique constraints in JPA. First, we did a little recap of the unique constraints. Then we discussed the @Column(unique=true) and @UniqueConstraint annotations to define unique constraints on a single column and multiple columns, respectively.

The code backing this article is available on GitHub. Once you're logged in as a Baeldung Pro Member, start learning and coding on the project.
Baeldung Pro – NPI EA (cat = Baeldung)
announcement - icon

Baeldung Pro comes with both absolutely No-Ads as well as finally with Dark Mode, for a clean learning experience:

>> Explore a clean Baeldung

Once the early-adopter seats are all used, the price will go up and stay at $33/year.

Partner – Microsoft – NPI EA (cat = Spring Boot)
announcement - icon

Azure Container Apps is a fully managed serverless container service that enables you to build and deploy modern, cloud-native Java applications and microservices at scale. It offers a simplified developer experience while providing the flexibility and portability of containers.

Of course, Azure Container Apps has really solid support for our ecosystem, from a number of build options, managed Java components, native metrics, dynamic logger, and quite a bit more.

To learn more about Java features on Azure Container Apps, visit the documentation page.

You can also ask questions and leave feedback on the Azure Container Apps GitHub page.

Partner – Orkes – NPI EA (cat = Spring)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

Partner – Orkes – NPI EA (tag = Microservices)
announcement - icon

Modern software architecture is often broken. Slow delivery leads to missed opportunities, innovation is stalled due to architectural complexities, and engineering resources are exceedingly expensive.

Orkes is the leading workflow orchestration platform built to enable teams to transform the way they develop, connect, and deploy applications, microservices, AI agents, and more.

With Orkes Conductor managed through Orkes Cloud, developers can focus on building mission critical applications without worrying about infrastructure maintenance to meet goals and, simply put, taking new products live faster and reducing total cost of ownership.

Try a 14-Day Free Trial of Orkes Conductor today.

eBook – HTTP Client – NPI EA (cat=HTTP Client-Side)
announcement - icon

The Apache HTTP Client is a very robust library, suitable for both simple and advanced use cases when testing HTTP endpoints. Check out our guide covering basic request and response handling, as well as security, cookies, timeouts, and more:

>> Download the eBook

eBook – Java Concurrency – NPI EA (cat=Java Concurrency)
announcement - icon

Handling concurrency in an application can be a tricky process with many potential pitfalls. A solid grasp of the fundamentals will go a long way to help minimize these issues.

Get started with understanding multi-threaded applications with our Java Concurrency guide:

>> Download the eBook

eBook – Java Streams – NPI EA (cat=Java Streams)
announcement - icon

Since its introduction in Java 8, the Stream API has become a staple of Java development. The basic operations like iterating, filtering, mapping sequences of elements are deceptively simple to use.

But these can also be overused and fall into some common pitfalls.

To get a better understanding on how Streams work and how to combine them with other language features, check out our guide to Java Streams:

>> Join Pro and download the eBook

eBook – Persistence – NPI EA (cat=Persistence)
announcement - icon

Working on getting your persistence layer right with Spring?

Explore the eBook

Course – LS – NPI EA (cat=REST)

announcement - icon

Get started with Spring Boot and with core Spring, through the Learn Spring course:

>> CHECK OUT THE COURSE

Course – Spring Sale 2025 – NPI EA (cat= Baeldung)
announcement - icon

Yes, we're now running our Spring Sale. All Courses are 25% off until 26th May, 2025:

>> EXPLORE ACCESS NOW

Course – Spring Sale 2025 – NPI (All)
announcement - icon

Yes, we're now running our Spring Sale. All Courses are 25% off until 26th May, 2025:

>> EXPLORE ACCESS NOW

Course – LSD – NPI (cat=JPA)
announcement - icon

Get started with Spring Data JPA through the reference Learn Spring Data JPA:

>> CHECK OUT THE COURSE

eBook Jackson – NPI EA – 3 (cat = Jackson)