# 2. Field/Column Mappings

## 1. @Id

### About

* `@Id` marks a field or property as the **primary key** of the entity.
* The **primary key** uniquely identifies each record in the database table.
* Every entity **must have exactly one primary key** field annotated with `@Id`.

### Important Points

* Without `@Id`, the JPA provider will **throw errors** — every entity must be identifiable uniquely.
* The field marked with `@Id` can be of types like `Long`, `Integer`, `UUID`, `String`, depending on the application.
* If no `@GeneratedValue` is used, the application itself is responsible for setting the ID.

### Syntax and Usage

```java
import jakarta.persistence.Entity;
import jakarta.persistence.Id;

@Entity
public class Employee {
    @Id
    private Long id;
    private String name;
}
```

Here, `id` is the primary key field.

## 2. @GeneratedValue

### About

* `@GeneratedValue` is used to **automatically generate the value** of the primary key field.
* It works together with `@Id`.
* You can specify different **strategies** for how the IDs are generated.

### Important Points

* Removes manual burden of assigning unique IDs.
* Allows consistent, reliable primary key generation, even in concurrent environments.
* Supports multiple generation strategies suitable for different databases.

### Syntax and Usage

```java
import jakarta.persistence.GeneratedValue;
import jakarta.persistence.GenerationType;
import jakarta.persistence.Id;

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

### Strategies for `@GeneratedValue`

#### 1. `GenerationType.AUTO`

* JPA **leaves the choice** of generation strategy to the **JPA provider** (like Hibernate).
* Hibernate will automatically pick the most appropriate strategy depending on the **underlying database** capabilities.

<table><thead><tr><th width="195.6796875">DB</th><th>Strategy selected by Hibernate</th></tr></thead><tbody><tr><td>MySQL</td><td><code>IDENTITY</code> (Auto Increment)</td></tr><tr><td>Oracle</td><td><code>SEQUENCE</code></td></tr><tr><td>H2</td><td><code>SEQUENCE</code></td></tr><tr><td>PostgreSQL</td><td><code>SEQUENCE</code></td></tr></tbody></table>

#### Key Points

* Portable: No need to change the code when changing DBs.
* Unpredictable: Exact generation behavior **depends on DB and provider**.
* Best suited for **simple apps** or when you don't care about ID mechanism.

#### Example

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

#### 2. `GenerationType.IDENTITY`

* The **database** handles primary key generation **using auto-increment columns**.
* Common in databases like **MySQL**, **PostgreSQL**, **SQL Server**.

#### How it Works

* We **don't send** an ID in the `INSERT` statement.
* Database **automatically assigns** the next number.
* After the insert, Hibernate/JPA **retrieves the generated ID**.

```sql
INSERT INTO employee (name, department) VALUES ('John Doe', 'IT');
-- DB automatically assigns id = 1
```

#### Key Points

* No need for a separate sequence object.
* **INSERT must happen immediately** — Hibernate can't batch inserts easily.
* Slightly **lower performance** if we need batch inserts.
* Not portable across databases (Oracle does not support auto-increment).

#### Example

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

#### 3. `GenerationType.SEQUENCE`

* Uses a **database sequence object** to generate primary keys.
* Highly efficient for **databases that support sequences** (e.g., **Oracle**, **PostgreSQL**, **H2**, **DB2**).

#### How it Works

* Before inserting the row, Hibernate issues a `SELECT nextval('sequence_name')` to fetch the next available ID.
* Then it uses this ID in the `INSERT` statement.

```sql
SELECT nextval('employee_seq');
INSERT INTO employee (id, name, department) VALUES (1001, 'John Doe', 'IT');
```

#### Key Points

* **Better performance** compared to `IDENTITY` because Hibernate can **preallocate IDs**.
* Fully supports **batch inserts** and **optimistic ID fetching**.
* You can **customize** sequence name, initial value, allocation size using `@SequenceGenerator`.
* More flexible and efficient in high-load systems.

#### Example

```java
@Entity
@SequenceGenerator(name="employee_seq", sequenceName = "employee_sequence", allocationSize=1)
public class Employee {
    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "employee_seq")
    private Long id;
}
```

**Attributes explained**

<table><thead><tr><th width="172.6015625">Attribute</th><th>Meaning</th></tr></thead><tbody><tr><td><code>name</code></td><td>Logical name for sequence generator.</td></tr><tr><td><code>sequenceName</code></td><td>Actual sequence name in DB.</td></tr><tr><td><code>allocationSize</code></td><td>Number of IDs fetched at a time (default = 50). Lower = more DB hits, higher = more memory.</td></tr></tbody></table>

**Note:** allocationSize > 1 gives better performance because it reduces DB round-trips.

#### 4. `GenerationType.TABLE`

* Simulates sequence behavior **using a database table**.
* Useful when **database does not support sequences or auto-increment** (e.g., older DBs).

#### How it Works

* A separate table (e.g., `hibernate_sequences`) stores next available IDs.
* Before insert, Hibernate selects and updates the value from this table.

Example

```sql
SELECT next_val FROM hibernate_sequences WHERE sequence_name = 'employee';
UPDATE hibernate_sequences SET next_val = next_val + 1 WHERE sequence_name = 'employee';
```

#### Key Points

* Works on any database — portable solution.
* Slow performance compared to `SEQUENCE`.
* High risk of contention in high-concurrency environments (locking issues).
* Should be avoided in very high-traffic systems unless no choice.

#### Example

```java
@Entity
@TableGenerator(
    name = "employee_gen",
    table = "id_generator",
    pkColumnName = "gen_name",
    valueColumnName = "gen_value",
    pkColumnValue = "employee_id",
    allocationSize = 1
)
public class Employee {
    @Id
    @GeneratedValue(strategy = GenerationType.TABLE, generator = "employee_gen")
    private Long id;
}
```

**Explanation of attributes**

<table><thead><tr><th width="193.4453125">Attribute</th><th>Description</th></tr></thead><tbody><tr><td><code>name</code></td><td>Logical name for table generator.</td></tr><tr><td><code>table</code></td><td>Table name used to store keys.</td></tr><tr><td><code>pkColumnName</code></td><td>Column that stores the key name (e.g., "employee_id").</td></tr><tr><td><code>valueColumnName</code></td><td>Column that stores the key value.</td></tr><tr><td><code>pkColumnValue</code></td><td>Specific key for this entity.</td></tr><tr><td><code>allocationSize</code></td><td>How many IDs to allocate at once.</td></tr></tbody></table>

### Quick Comparison of Strategies

| Strategy   | Who generates ID?        | Supports Batch Inserts? | Performance | Portability |
| ---------- | ------------------------ | ----------------------- | ----------- | ----------- |
| `AUTO`     | JPA Provider decides     | Depends                 | Medium      | High        |
| `IDENTITY` | Database auto-increment  | No                      | Medium-Low  | Low         |
| `SEQUENCE` | Database sequence object | Yes                     | High        | Medium-High |
| `TABLE`    | Separate table           | No                      | Low         | Very High   |

## 3. @Column

### About

* `@Column` is used to **customize the mapping** between an entity field and a database column.
* By default, JPA maps fields to columns of the same name, but `@Column` lets you **override** or **fine-tune** that behavior.

### Important Points

* It controls column name, length, nullable constraints, uniqueness, precision, and scale.
* It is **optional** — if not present, JPA assumes default mapping.
* It improves control over database schema generation.

### Syntax and Usage

```java
import jakarta.persistence.Column;

@Entity
public class Employee {
    @Id
    private Long id;

    @Column(name = "emp_name", nullable = false, length = 100)
    private String name;
}
```

### Attributes of `@Column`

<table data-full-width="true"><thead><tr><th width="157.00390625">Attribute</th><th width="446.421875">Description</th><th>Example</th></tr></thead><tbody><tr><td><code>name</code></td><td>Maps the field to a different column name.</td><td><code>@Column(name = "emp_name")</code></td></tr><tr><td><code>nullable</code></td><td>Specifies if the column can contain <code>NULL</code> values. Default is <code>true</code>.</td><td><code>@Column(nullable = false)</code></td></tr><tr><td><code>unique</code></td><td>Adds a unique constraint to the column.</td><td><code>@Column(unique = true)</code></td></tr><tr><td><code>length</code></td><td>Defines the maximum column size (for <code>VARCHAR</code>/<code>CHAR</code>). Default is 255.</td><td><code>@Column(length = 100)</code></td></tr><tr><td><code>insertable</code></td><td>If false, column is not included in SQL INSERTs.</td><td><code>@Column(insertable = false)</code></td></tr><tr><td><code>updatable</code></td><td>If false, column is not included in SQL UPDATEs.</td><td><code>@Column(updatable = false)</code></td></tr><tr><td><code>precision</code></td><td>For <code>BigDecimal</code>, defines the total number of digits.</td><td><code>@Column(precision = 10)</code></td></tr><tr><td><code>scale</code></td><td>For <code>BigDecimal</code>, defines number of digits after decimal point.</td><td><code>@Column(scale = 2)</code></td></tr><tr><td><code>columnDefinition</code></td><td>Defines DDL directly (rarely used).</td><td><code>@Column(columnDefinition = "TEXT")</code></td></tr></tbody></table>

### Practical Usage Scenarios

* If your DB column name is different from Java field name, always specify `@Column(name = "...")`.
* For fields like emails, usernames, use `@Column(unique = true)`.
* For fields that should not be updated after insert (e.g., created date), use `@Column(updatable = false)`.
* Use `length` wisely for optimizing string storage.
* For monetary values (`BigDecimal`), define `precision` and `scale` to avoid rounding issues.
