# 1. Entity and Table Mappings

## 1. @Entity

### About

* `@Entity` is a JPA (Java Persistence API) annotation.
* It marks a plain Java class as an entity bean, which means this class will be mapped to a relational database table.
* When the persistence provider (like Hibernate) sees a class annotated with `@Entity`, it treats the class as a persistent entity, capable of being managed, saved, deleted, and queried from the database.

### Important Points

* **Mandatory for persistence**: Only classes annotated with `@Entity` are recognized as entities by the JPA provider.
* **No-argument constructor required**: The class must have a public or protected no-argument constructor (this is needed by JPA at runtime via reflection).
* **Serializable**: Although not mandatory by specification, it is recommended that entity classes **implement `Serializable`** for best practices, especially in distributed systems.
* **Uniquely identifiable**: Every entity must have a primary key field, which is annotated with `@Id`.
* **Class cannot be final**: The JPA provider may need to subclass or proxy the entity.
* **Fields/Properties**: The class can either have fields or getter/setter methods that are persisted, depending on whether you use field access or property access (determined by where the `@Id` is placed).

### Syntax and Usage

```java
import jakarta.persistence.Entity;

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

    private String name;
    private String department;
}
```

Here:

* `Employee` is now a **managed entity**.
* JPA will create a table for it or map it to an existing table.

### Rules for Using `@Entity`

<table><thead><tr><th width="206.4765625">Rule</th><th>Description</th></tr></thead><tbody><tr><td>Entity name</td><td>If no name is specified, the class name is used as the entity name.</td></tr><tr><td>Table name</td><td>If no <code>@Table</code> annotation is present, the table name defaults to the entity name (case-sensitive, depending on database).</td></tr><tr><td>Must not be final</td><td>JPA providers use proxies; final classes cannot be proxied easily.</td></tr><tr><td>Must have a primary key</td><td>Without an <code>@Id</code>, the entity cannot be managed.</td></tr><tr><td>No-arg constructor</td><td>Required by the persistence provider.</td></tr></tbody></table>

### Optional Attributes of `@Entity`

```java
@Entity(name = "EmployeeEntity")
```

* **name**: Defines the name of the entity (used in JPQL queries). Defaults to the class name if not provided.
* Note: The name has nothing to do with the table name in the database (that's handled by `@Table`).

## 2. @Table

### About

* `@Table` is a JPA annotation used to customize the database table that an entity is mapped to.
* By default, if `@Table` is not specified, JPA uses the class name as the table name.
* `@Table` allows developers to control the table name, schema, catalog, and indexes.

### Important Points

* **Customization of mapping**: `@Table` tells JPA what actual database table should back the entity.
* **Optional**: It is **not mandatory**. Without `@Table`, the entity will map to a table named exactly like the entity class.
* **Defines schema/catalog**: It can specify the **database schema** or **catalog** in multi-schema setups.
* **Define unique constraints**: You can define **database-level unique constraints** across one or more columns.

### Syntax and Usage

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

@Entity
@Table(name = "employees", schema = "company", catalog = "corporate")
public class Employee {
    @Id
    private Long id;
    private String name;
}
```

Here:

* `employees` is the **actual table name** in the `company` schema of the `corporate` catalog.
* The `Employee` entity will persist records into `corporate.company.employees`.

### Attributes of `@Table`

<table data-full-width="true"><thead><tr><th width="188.3125">Attribute</th><th width="274.43359375">Description</th><th>Example</th></tr></thead><tbody><tr><td><strong>name</strong></td><td>The name of the database table.</td><td><code>@Table(name = "employees")</code></td></tr><tr><td><strong>schema</strong></td><td>Name of the database schema.</td><td><code>@Table(schema = "company")</code></td></tr><tr><td><strong>catalog</strong></td><td>Name of the database catalog.</td><td><code>@Table(catalog = "corporate")</code></td></tr><tr><td><strong>uniqueConstraints</strong></td><td>Defines unique constraints on one or more columns.</td><td><code>@Table(uniqueConstraints = @UniqueConstraint(columnNames = {"email"}))</code></td></tr><tr><td><strong>indexes</strong></td><td>Defines indexes on one or more columns (since JPA 2.1).</td><td><code>@Table(indexes = @Index(name = "idx_name", columnList = "name"))</code></td></tr></tbody></table>

### Practical Details About Attributes

#### `name`

* Specifies the table's name in the database.
* If omitted, the entity class name is used.
* If different from the entity name, always specify `name`.

```java
@Table(name = "emp_details")
```

#### `schema`

* Useful when your database is logically divided into **schemas** (especially common in Oracle, PostgreSQL).
* If your table resides in a different schema, you must specify it.

```java
@Table(schema = "hr")
```

#### `catalog`

* Refers to the database catalog.
* Rarely used compared to `schema`.
* In some RDBMS like MySQL, catalog and database are the same.

```java
@Table(catalog = "employees_db")
```

#### `uniqueConstraints`

* You can define one or more **columns** that must have unique values.
* It **generates a UNIQUE constraint** at the database level.

```java
@Table(uniqueConstraints = @UniqueConstraint(columnNames = {"email"}))
```

Means the `email` column must be unique for all rows.

#### `indexes`

* Introduced in **JPA 2.1**.
* Specifies **index creation** on columns.
* Helps in performance optimization at the database level.

```java
@Table(indexes = @Index(name = "idx_employee_name", columnList = "name"))
```

Creates an index named `idx_employee_name` on the `name` column.
