JPA
MySQL
autoincrement
annotations
database

How to annotate MYSQL autoincrement field with JPA annotations

Master System Design with Codemia

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

Introduction

For a MySQL AUTO_INCREMENT primary key, the usual JPA mapping is @Id together with @GeneratedValue(strategy = GenerationType.IDENTITY). That tells the persistence provider that the database, not the application, is responsible for generating the identifier during insert.

The Basic Mapping

Here is the common entity definition.

java
1import jakarta.persistence.Entity;
2import jakarta.persistence.GeneratedValue;
3import jakarta.persistence.GenerationType;
4import jakarta.persistence.Id;
5import jakarta.persistence.Table;
6
7@Entity
8@Table(name = "users")
9public class User {
10
11    @Id
12    @GeneratedValue(strategy = GenerationType.IDENTITY)
13    private Long id;
14
15    private String username;
16
17    public Long getId() {
18        return id;
19    }
20
21    public String getUsername() {
22        return username;
23    }
24
25    public void setUsername(String username) {
26        this.username = username;
27    }
28}

GenerationType.IDENTITY is the important part. It maps naturally to MySQL's auto-increment behavior, where the row is inserted first and the database returns the generated key.

Why IDENTITY Is the Right Strategy for MySQL Auto-Increment

JPA offers several generation strategies, but they are not interchangeable.

  • 'IDENTITY: the database generates the key during insert'
  • 'SEQUENCE: for databases with sequence objects'
  • 'TABLE: uses a separate table to emulate sequence generation'
  • 'AUTO: lets the provider choose'

For a MySQL column defined with AUTO_INCREMENT, IDENTITY is the explicit and correct choice. It matches the underlying database feature directly instead of depending on provider inference.

Let the Database Generate the Value

Do not set the id field manually before persisting the entity.

java
1User user = new User();
2user.setUsername("mark");
3entityManager.persist(user);
4System.out.println(user.getId());

After persist and flush, JPA obtains the generated key from MySQL and populates the entity field. If you assign the primary key yourself while also declaring IDENTITY, you are mixing two incompatible strategies.

Wrapper Types Are Usually Better Than Primitives

Use Long or Integer instead of primitive long or int for generated IDs. A nullable wrapper cleanly represents the pre-persist state where the entity has no database identity yet.

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

With a primitive type, 0 can be confused with a meaningful application value even though the row has not been inserted yet.

Match the Database Schema

Your MySQL schema should define the primary key column accordingly.

sql
1CREATE TABLE users (
2    id BIGINT NOT NULL AUTO_INCREMENT,
3    username VARCHAR(255) NOT NULL,
4    PRIMARY KEY (id)
5);

If the table is not actually configured with AUTO_INCREMENT, the JPA annotation alone will not manufacture the right database behavior. The entity mapping and schema must agree.

One Important Behavior Difference

IDENTITY generation usually means the insert must happen before the identifier is known. That can affect batching behavior in some JPA providers. It is not usually a correctness problem, but it matters when people compare IDENTITY with sequence-based strategies on other databases.

For MySQL auto-increment, that tradeoff is normal and expected.

Common Pitfalls

  • Using GenerationType.AUTO and assuming it will always choose the intended MySQL behavior.
  • Setting the ID field manually even though the database is supposed to generate it.
  • Using SEQUENCE with MySQL auto-increment tables, which does not match the database model.
  • Declaring the JPA annotations correctly while forgetting to define AUTO_INCREMENT in the actual schema.
  • Using a primitive ID type when a nullable wrapper would better represent the entity lifecycle.

Summary

  • Map a MySQL auto-increment primary key with @Id and @GeneratedValue(strategy = GenerationType.IDENTITY).
  • Let MySQL generate the identifier during insert.
  • Prefer Long or Integer over primitive numeric types for generated IDs.
  • Keep the JPA mapping and database schema consistent.
  • 'IDENTITY is the standard explicit strategy for MySQL AUTO_INCREMENT columns.'

Course illustration
Course illustration

All Rights Reserved.