Skip to main content

Command Palette

Search for a command to run...

Module - Generated Value - Sequence Generator - Mapping

Published
•9 min read•View as Markdown
package com.example.demo.module;

import jakarta.persistence.*;
import lombok.Getter;
import lombok.Setter;

@Entity
@Table(name = "Profile")
@Getter
@Setter
public class Profile {

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

    @OneToOne
    @JoinColumn(name = "users_id") // foreign key
    private Users applicant;

    private String name;
    private String email;
    private String phone;
    private String skills;
    private String education;
    private String experience;
    private String resumeFileAddress;
}

Summary of the Profile Entity

  • The Profile class is a JPA entity representing a Profile table in the database.

  • Uses Jakarta Persistence annotations for ORM mapping.

  • Fields:

    • id – Primary key, auto-generated using identity strategy.

    • applicant – A one-to-one relationship with the Users entity, mapped via users_id foreign key.

    • Other fields store profile information: name, email, phone, skills, education, experience, resumeFileAddress.

  • Uses Lombok @Getter and @Setter for automatic getter and setter generation.

Primary Key Generation

JPA specification supports 4 different types of primary key generation strategies

  1. GenerationType.AUTO

  2. GenerationType.IDENTITY

  3. GenerationType.SEQUENCE

  4. GenerationType.Table

1. GenerationType.AUTO

  • Hibernate chooses the best strategy based on your database.

  • It might pick SEQUENCE, IDENTITY, or TABLE depending on DB support.

Example:

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;

    private String name;
}

Notes:

  • Simple to use, good for cross-DB portability.

  • Hibernate decides which strategy works best.


2. GenerationType.IDENTITY

  • Uses database auto-increment / identity columns.

  • Common in MySQL, SQL Server.

Example:

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;
}

Notes:

  • DB automatically generates ID during insert.

  • Hibernate cannot batch inserts efficiently because it needs the ID immediately after insert.

  • No sequence or extra table is used.

2. What happens on insert

  1. You create a new entity in Java:
User u = new User();
u.setName("Alice");
entityManager.persist(u);
  1. Hibernate executes an INSERT statement without the ID:
INSERT INTO user (name) VALUES ('Alice');
  1. The database automatically assigns the next auto-increment ID (e.g., 1).

  2. Hibernate retrieves the generated ID from the database using JDBC API:

  • In MySQL: getGeneratedKeys()

  • In PostgreSQL: RETURNING id

  1. Hibernate then sets the ID on the entity:
u.getId(); // 1

3. GenerationType.SEQUENCE

  • Uses a database sequence object (if DB supports it).

  • Hibernate prefetches IDs using allocationSize.

Example:

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "user_seq")
    @SequenceGenerator(name = "user_seq", sequenceName = "user_sequence", allocationSize = 5)
    private Long id;

    private String name;
}

Notes:

  • Efficient, supports batch inserts.

  • DB sequence internally tracks the next value.

  • Safe for multiple app instances.

  • No explicit table is created.

First time an ID is needed:

  • Hibernate asks the database sequence for the next value.

  • DB sequence returns 1.

  • Hibernate internally reserves IDs 1 to 5 in memory.

  • Next inserts:

    • Hibernate just uses IDs 2, 3, 4, 5 from memory—no DB call needed.
  • After using up 1–5, Hibernate asks the DB sequence again:

    • DB sequence increments (next value = 6)

    • Hibernate reserves 6–10


4. GenerationType.TABLE

  • Uses a Hibernate-managed table to simulate sequences.

  • Useful for DBs without native sequences.

Example:

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "user_tab")
    @TableGenerator(
        name = "user_tab",
        table = "hibernate_sequences",
        pkColumnName = "sequence_name",
        valueColumnName = "next_val",
        allocationSize = 5
    )
    private Long id;

    private String name;
}

Notes:

  • Hibernate reads/updates the table to generate IDs.

  • Works on any database.

  • Slightly slower than SEQUENCE due to extra SELECT + UPDATE.


5. Summary Table

StrategyHow it worksDB Object Needed?PerformanceMultiple App Instances Safe?Extra Table?
AUTOHibernate picks bestDependsGood✅ YesMaybe
IDENTITYDB auto-increment columnYesModerate✅ Yes❌ No
SEQUENCEDB sequence objectYesFast, efficient✅ Yes❌ No
TABLEHibernate table tracks IDNoSlower✅ Yes✅ Yes

Key Takeaways

  1. Use SEQUENCE if your DB supports it → fastest, safe for multiple app instances.

  2. Use IDENTITY for auto-increment DBs → simple, but not batch-friendly.

  3. Use TABLE only if DB has no sequence support.

  4. AUTO is convenient for cross-DB portability.

1. One-to-One Mapping

Scenario: A User has one Profile.

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @OneToOne(mappedBy = "user", cascade = CascadeType.ALL)
    private Profile profile;

    // getters and setters
}

@Entity
public class Profile {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String email;

    @OneToOne
    @JoinColumn(name = "user_id")  // foreign key in Profile table
    private User user;

    // getters and setters
}

Explanation:

  • Profile has a foreign key to User.

  • mappedBy = "user" tells Hibernate that User is the inverse side.

  • cascade = CascadeType.ALL ensures saving User also saves Profile.

  • Profile owns the relationship (@JoinColumn → foreign key).

  • User is the inverse side (mappedBy = "user").

  • You can now navigate in both directions:

Repository Example:

public interface UserRepository extends JpaRepository<User, Long> {}
public interface ProfileRepository extends JpaRepository<Profile, Long> {}

Usage:

User user = new User();
user.setName("Alice");

Profile profile = new Profile();
profile.setEmail("alice@example.com");
profile.setUser(user);

user.setProfile(profile);

userRepository.save(user);  // Saves both user and profile

2. One-to-Many Mapping

Scenario: A User can have multiple Posts.

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @OneToMany(mappedBy = "user", cascade = CascadeType.ALL)
    private List<Post> posts = new ArrayList<>();

    // getters and setters
}

@Entity
public class Post {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String title;

    @ManyToOne
    @JoinColumn(name = "user_id")  // foreign key in Post table
    private User user;

    // getters and setters
}

Explanation:

  • Post table has a foreign key user_id referring to User.

  • mappedBy = "user" indicates the User entity owns the relationship.

  • cascade = CascadeType.ALL ensures saving a User saves all their Posts.

  • Post owns the foreign key (user_id).

  • User is the inverse side (mappedBy = "user").

  • Now you can navigate both ways:

Usage Example:

User user = new User();
user.setName("Bob");

Post post1 = new Post();
post1.setTitle("First Post");
post1.setUser(user);

Post post2 = new Post();
post2.setTitle("Second Post");
post2.setUser(user);

user.getPosts().add(post1);
user.getPosts().add(post2);

userRepository.save(user);  // Saves user and both posts

✅ Key Points

MappingForeign Key LocationCascade Option ExampleExample Scenario
@OneToOneProfile tableALLUser → Profile
@OneToManyPost tableALLUser → multiple Posts

What mappedBy means

  • mappedBy tells Hibernate:
    “This side is the inverse side of the relationship; the other side owns the foreign key.”

  • Only the owner side manages the database foreign key.

  • The inverse side just maps to the owner for navigation purposes.

4. Key Points

SideRoleForeign Key Managed?mappedBy needed?
OwnerManages DB relationshipYes❌ No
Inverse (mappedBy)Just navigates relationshipNo✅ Yes
  • Without mappedBy, Hibernate will create an extra join table to manage the relationship.

  • Using mappedBy avoids extra tables and makes it truly bidirectional.

1. Unidirectional One-to-One

Scenario: A User has one Profile, but Profile does not have a reference back to User.

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "profile_id")  // FK in User table
    private Profile profile;

    // getters and setters
}

@Entity
public class Profile {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String email;

    // No reference to User → unidirectional
    // getters and setters
}

Explanation:

  • User has a profile_id column → foreign key.

  • Profile does not know about User.

  • Navigation: User → Profile, but not Profile → User.

Usage Example:

Profile profile = new Profile();
profile.setEmail("alice@example.com");

User user = new User();
user.setName("Alice");
user.setProfile(profile);

userRepository.save(user);  // Saves both User and Profile

2. Unidirectional Many-to-One

Scenario: Many Posts belong to one User, but User does not have a collection of posts.

@Entity
public class Post {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String title;

    @ManyToOne
    @JoinColumn(name = "user_id")  // FK in Post table
    private User user;

    // getters and setters
}

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    private String name;

    // No collection of posts → unidirectional
    // getters and setters
}

Explanation:

  • Post table has a user_id column → foreign key.

  • User does not have a List<Post> collection.

  • Navigation: Post → User, but not User → Posts.

Usage Example:

User user = new User();
user.setName("Bob");
userRepository.save(user);

Post post1 = new Post();
post1.setTitle("Post 1");
post1.setUser(user);

Post post2 = new Post();
post2.setTitle("Post 2");
post2.setUser(user);

postRepository.save(post1);
postRepository.save(post2);

✅ Key Points

Mapping TypeFK LocationNavigation AvailableExtra Table?Example Scenario
One-to-One (uni)User table (profile_id)User → Profile❌ NoUser has Profile
Many-to-One (uni)Post table (user_id)Post → User❌ NoMany posts belong to User

So in short:

  • mappedBy = bidirectional, inverse side, does not own FK

  • No mappedBy = unidirectional, or Hibernate creates extra table


Why Extra Table ? if not mapped / not referenced ?

  • Post has a foreign key column (user_id).

  • User has a OneToMany without mappedBy.

Scenario:

@Entity
public class User {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @OneToMany  // No mappedBy
    private List<Post> posts = new ArrayList<>();
}

@Entity
public class Post {
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;

    @ManyToOne
    @JoinColumn(name = "user_id")  // FK column in Post
    private User user;
}

1. What Hibernate sees

  • Post.user → owner side → has a foreign key column user_id in Post table. ✅

  • User.posts → OneToMany without mappedBy → Hibernate thinks this is a separate unidirectional relationship.

💡 Important: Hibernate does not know that User.posts is the inverse of Post.user.


2. What Hibernate does

  • Creates an extra join table for the User.posts collection.

By default, Hibernate might name it: user_posts

user_idposts_id
1101
1102

3. Database tables now

  1. User table
idname
1Alice
2Bob
  1. Post table (FK from ManyToOne)
idtitleuser_id
101Post11
102Post21
  1. Join table (user_posts) created by OneToMany without mappedBy
user_idposts_id
1101
1102

4. Why does this happen

  • Without mappedBy, Hibernate treats User.posts as another independent relationship.

  • It cannot reuse the user_id in Post because it doesn’t know they are the same relationship.

  • So it creates a join table to safely store the mapping.


✅ Key takeaway:

  • mappedBy tells Hibernate: use the foreign key in Post → no extra table.

  • Without mappedBy → Hibernate creates a join table even if a foreign key already exists in Post.