> For the complete documentation index, see [llms.txt](https://www.pranaypourkar.co.in/the-programmers-guide/llms.txt). Markdown versions of documentation pages are available by appending `.md` to page URLs; this page is available as [Markdown](https://www.pranaypourkar.co.in/the-programmers-guide/spring/spring-features/spring-persistence/jpa-java-persistence-api/orm-mapping-annotations/3.-relationship-mappings.md).

# 3. Relationship Mappings

## 1. @OneToOne

### About

* `@OneToOne` defines a **one-to-one** relationship **between two entity classes**.
* It means **each instance** of Entity A **is associated with exactly one instance** of Entity B, and vice versa.
* It is **bidirectional** or **unidirectional** based on how we model the relationship.

{% hint style="info" %}
Example - Employee and EmployeeDetails

* Each Employee has **one** EmployeeDetails record.
* Each EmployeeDetails is linked to exactly **one** Employee.
  {% endhint %}

### Syntax

```java
@Entity
public class Employee {
    
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String name;
    
    @OneToOne
    private EmployeeDetails details;
}
```

This maps a simple **unidirectional** `@OneToOne` — Employee has a link to EmployeeDetails.

## Attributes

<table data-full-width="true"><thead><tr><th width="187.12890625">Attribute</th><th>Description</th></tr></thead><tbody><tr><td><code>mappedBy</code></td><td>Indicates the <strong>inverse</strong> side of the relationship (used in bidirectional mapping).</td></tr><tr><td><code>cascade</code></td><td>Defines cascade operations like persist, remove, merge etc.</td></tr><tr><td><code>fetch</code></td><td>Defines when to fetch related entity: <code>EAGER</code> (default) or <code>LAZY</code>.</td></tr><tr><td><code>optional</code></td><td>Whether the relationship is mandatory (<code>false</code>) or optional (<code>true</code>). Default is <code>true</code>.</td></tr><tr><td><code>orphanRemoval</code></td><td>Whether to automatically remove orphaned records.</td></tr></tbody></table>

### How Relationships Are Stored in Database

* Usually through a **foreign key**.
* Typically one table has a **foreign key reference** to the other table.

For example:

```sql
create table employee (
    id bigint not null,
    name varchar(255),
    details_id bigint,
    primary key (id),
    foreign key (details_id) references employee_details(id)
);

create table employee_details (
    id bigint not null,
    address varchar(255),
    phone_number varchar(255),
    primary key (id)
);
```

#### 1. Unidirectional `@OneToOne`

Only one entity knows about the relationship.

```java
@Entity
public class Employee {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String name;
    
    @OneToOne(cascade = CascadeType.ALL)
    @JoinColumn(name = "details_id", referencedColumnName = "id")
    private EmployeeDetails details;
}
```

```java
@Entity
public class EmployeeDetails {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String address;
    private String phoneNumber;
}
```

* `@JoinColumn(name = "details_id", referencedColumnName = "id")`
  * `details_id` column in `employee` table holds the foreign key referencing `employee_details(id)`.
* `cascade = CascadeType.ALL`
  * If we persist or delete an Employee, EmployeeDetails will automatically be persisted or deleted too.

#### 2. Bidirectional `@OneToOne`

Both entities are aware of the relationship.

```java
@Entity
public class Employee {

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

    private String name;

    @OneToOne(mappedBy = "employee", cascade = CascadeType.ALL)
    private EmployeeDetails details;
}
```

```java
@Entity
public class EmployeeDetails {

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

    private String address;
    private String phoneNumber;

    @OneToOne
    @JoinColumn(name = "employee_id", referencedColumnName = "id")
    private Employee employee;
}
```

* `EmployeeDetails` owns the relationship (`@JoinColumn` is there).
* `Employee` just references it through `mappedBy = "employee"`.
* `mappedBy` tells JPA that the **foreign key is managed by the other side** (i.e., EmployeeDetails).

{% hint style="info" %}

## Cascade Types

We often want operations on the parent to affect the child entity too.\
Typical cascade types with `@OneToOne`:

* `CascadeType.PERSIST`: Save parent ➔ saves child.
* `CascadeType.REMOVE`: Delete parent ➔ deletes child.
* `CascadeType.MERGE`: Merge parent ➔ merges child.
* `CascadeType.ALL`: All operations (persist, merge, remove, refresh, detach).
  {% endhint %}

{% hint style="info" %}
FetchType

* `FetchType.EAGER` (Default): Child entity is **loaded immediately** with parent entity.
* `FetchType.LAZY`: Child entity is **loaded only when accessed**.

In `@OneToOne`, default is **EAGER** (unlike `@OneToMany` where it’s LAZY).
{% endhint %}

## 2. @OneToMany

### About

* `@OneToMany` defines a **one-to-many** relationship **between two entity classes**.
* It means **one instance** of Entity A **is associated with multiple instances** of Entity B.
* For example, **one Department** has **many Employees**.

### Syntax

```java
@Entity
public class Department {

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

    private String name;

    @OneToMany
    private List<Employee> employees;
}
```

This is a **unidirectional** mapping — Department has a list of Employees.

### Attributes

<table><thead><tr><th width="166.01953125">Attribute</th><th>Description</th></tr></thead><tbody><tr><td><code>mappedBy</code></td><td>Specifies that this side is the <strong>inverse side</strong> (non-owning side).</td></tr><tr><td><code>cascade</code></td><td>Propagate operations (persist, merge, remove, etc.).</td></tr><tr><td><code>fetch</code></td><td><code>LAZY</code> (default) or <code>EAGER</code> fetching behavior.</td></tr><tr><td><code>orphanRemoval</code></td><td>Automatically remove child records if they are no longer referenced.</td></tr></tbody></table>

## How It Is Mapped in Database ?

Usually with a **foreign key** in the child table.

```sql
create table department (
    id bigint not null,
    name varchar(255),
    primary key (id)
);

create table employee (
    id bigint not null,
    name varchar(255),
    department_id bigint,
    primary key (id),
    foreign key (department_id) references department(id)
);
```

* The `employee` table holds a **foreign key** (`department_id`) pointing to `department(id)`.

#### 1. Unidirectional `@OneToMany`

Only one side (Department) knows about the relationship.\
But **foreign key is still in child table** (Employee).

```java
@Entity
public class Department {

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

    private String name;

    @OneToMany(cascade = CascadeType.ALL)
    @JoinColumn(name = "department_id") // Important
    private List<Employee> employees = new ArrayList<>();
}
```

```java
@Entity
public class Employee {

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

    private String name;
}
```

* `@JoinColumn(name = "department_id")` tells Hibernate to use **department\_id** in the Employee table as a foreign key.
* **Without** `@JoinColumn`, Hibernate would create an unnecessary **join table** (bad for performance if not needed).
* `cascade = CascadeType.ALL` will propagate persist, remove, etc.

#### 2. Bidirectional `@OneToMany` and `@ManyToOne`

Both sides know the relationship.

```java
@Entity
public class Department {

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

    private String name;

    @OneToMany(mappedBy = "department", cascade = CascadeType.ALL, orphanRemoval = true)
    private List<Employee> employees = new ArrayList<>();
}
```

```java
@Entity
public class Employee {

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

    private String name;

    @ManyToOne(fetch = FetchType.LAZY)
    @JoinColumn(name = "department_id")
    private Department department;
}
```

* `Department` is the **inverse side** (`mappedBy = "department"`).
* `Employee` owns the foreign key (`@JoinColumn(name = "department_id")`).
* `orphanRemoval = true` means if we remove an Employee from Department's employee list, Hibernate deletes it.

{% hint style="info" %}
Common cascade types:

* `CascadeType.PERSIST`: When saving Department, Employees are saved automatically.
* `CascadeType.REMOVE`: Deleting Department deletes Employees.
* `CascadeType.MERGE`: Merging Department merges Employees.
* `CascadeType.ALL`: All operations cascaded.
  {% endhint %}

{% hint style="info" %}
Fetch Type

`FetchType.LAZY` (default) -> Child entities (List\<Employee>) are **loaded only when accessed**.

FetchType.EAGER -> Child entities are **loaded immediately** with parent entity.

* `@OneToMany` is **default LAZY**.
* Be careful while changing it to EAGER — it can cause **performance issues** if there are lots of child records.
  {% endhint %}

{% hint style="info" %}
Orphan Removal

* Setting `orphanRemoval = true` **automatically deletes** Employees that are **removed** from the Department’s list.

```java
department.getEmployees().remove(employee);
```

Hibernate will **DELETE** that Employee from DB.
{% endhint %}

## 3. @ManyToOne

### About

* `@ManyToOne` defines a **many-to-one** relationship between two entities.
* It means **many instances** of Entity A are associated with **one instance** of Entity B.
* Example: **Many Employees** belong to **one Department**.

### Syntax

```java
@Entity
public class Employee {

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

    private String name;

    @ManyToOne
    private Department department;
}
```

This is a simple way to map Employee ➔ Department.

### Attributes

<table><thead><tr><th width="152.640625">Attribute</th><th>Description</th></tr></thead><tbody><tr><td><code>fetch</code></td><td>Defines loading strategy: <code>EAGER</code> (default) or <code>LAZY</code>.</td></tr><tr><td><code>optional</code></td><td>Defines if the association is mandatory (<code>false</code>) or optional (<code>true</code>).</td></tr><tr><td><code>cascade</code></td><td>Defines cascading of operations (persist, merge, remove, etc.).</td></tr><tr><td><code>targetEntity</code></td><td>Defines the class type explicitly if necessary (rarely used).</td></tr></tbody></table>

### How It Is Mapped in Database ?

* The **foreign key** is created in the table of the owning entity (Employee).

```sql
create table department (
    id bigint not null,
    name varchar(255),
    primary key (id)
);

create table employee (
    id bigint not null,
    name varchar(255),
    department_id bigint,
    primary key (id),
    foreign key (department_id) references department(id)
);
```

* `employee.department_id` points to `department.id`.

#### Entity Classes

```java
@Entity
public class Department {

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

    private String name;
}
```

```java
@Entity
public class Employee {

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

    private String name;

    @ManyToOne(fetch = FetchType.LAZY, optional = false)
    @JoinColumn(name = "department_id")  // Explicit foreign key column name
    private Department department;
}
```

* `@ManyToOne` is placed on the field in the owning entity (Employee).
* `@JoinColumn(name = "department_id")` maps the foreign key column.
* `fetch = FetchType.LAZY` means Department will not be loaded until needed.
* `optional = false` means the Employee **must** have a Department (null not allowed).

{% hint style="info" %}
We can set cascade operations:

```java
@ManyToOne(cascade = CascadeType.ALL)
private Department department;
```

But **careful** — usually we **don’t** cascade from child to parent!\
(We don't want saving Employee to randomly save/update Department.)

**Best Practice:** Avoid cascade for `@ManyToOne` unless there is a strong reason.
{% endhint %}

{% hint style="info" %}
Fetch Type

FetchType.EAGER (default) -> Always loads the Department with the Employee.

FetchType.LAZY -> Loads the Department **only when accessed**.

**Note:**

* In `@ManyToOne`, **default is EAGER** (unlike `@OneToMany` where default is LAZY).
* It is **recommended** to manually set it to `LAZY` for large data models to avoid performance issues.
  {% endhint %}

{% hint style="info" %}
Optional Attribute

optional = true (default) -> Employee can exist without a Department (foreign key can be null).

optional = false -> Department is required for Employee (foreign key must not be null).

If we set `optional = false`, Hibernate generates `NOT NULL` constraint on `department_id` in `employee` table.
{% endhint %}

## 4. @ManyToMany

### About

* `@ManyToMany` defines a **many-to-many** relationship between two entities.
* It means **many instances** of Entity A are related to **many instances** of Entity B.
* Example: **Many Employees** can work on **many Projects**.

### Syntax

```java
@Entity
public class Student {

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

    private String name;

    @ManyToMany
    private List<Course> courses;
}
```

This creates a **many-to-many** relation between `Student` and `Course`

## Attributes

<table><thead><tr><th width="175.765625">Attribute</th><th>Description</th></tr></thead><tbody><tr><td><code>fetch</code></td><td>Defines loading strategy: <code>LAZY</code> (default) or <code>EAGER</code>.</td></tr><tr><td><code>cascade</code></td><td>Defines cascade operations on associated entities.</td></tr><tr><td><code>targetEntity</code></td><td>Explicitly defines associated class if needed.</td></tr></tbody></table>

### How It Is Mapped in Database ?

* JPA creates an **intermediate join table** to manage the association.

```sql
create table student (
    id bigint not null,
    name varchar(255),
    primary key (id)
);

create table course (
    id bigint not null,
    title varchar(255),
    primary key (id)
);

create table student_course (
    student_id bigint not null,
    course_id bigint not null,
    primary key (student_id, course_id),
    foreign key (student_id) references student(id),
    foreign key (course_id) references course(id)
);
```

**@ManyToMany** always requires an intermediate **join table** because relational databases **do not** support direct many-to-many relations.

The **join table** holds two foreign keys:

* One pointing to Entity A.
* One pointing to Entity B.

The join table can optionally have a **composite primary key** (both foreign keys together).

#### 1. **Unidirectional `@ManyToMany` Mapping**

* **One Entity knows** about the other.
* The association is **one-way**.
* Only the **owning entity** manages the relationship.
* Other entity (target entity) does **NOT know** about the relation.

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

    private String name;

    @ManyToMany
    @JoinTable(
        name = "student_course",
        joinColumns = @JoinColumn(name = "student_id"),
        inverseJoinColumns = @JoinColumn(name = "course_id")
    )
    private List<Course> courses = new ArrayList<>();
}
```

```java
@Entity
public class Course {

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

    private String title;
}
```

#### Generated Database Tables

<table data-full-width="true"><thead><tr><th width="139.05078125">Table</th><th width="183.7265625">Columns</th><th width="333.0234375">Primary Key</th><th>Foreign Keys</th></tr></thead><tbody><tr><td>student</td><td>id, name</td><td>id</td><td>-</td></tr><tr><td>course</td><td>id, title</td><td>id</td><td>-</td></tr><tr><td>student_course</td><td>student_id, course_id</td><td>(student_id, course_id) composite key</td><td>FK (student_id) → student(id)<br>FK (course_id) → course(id)</td></tr></tbody></table>

* **Join Table (student\_course)** is fully managed by **Student**.
* **Course** does not know anything about Students.

#### Important

* Since `Course` does not have any `@ManyToMany(mappedBy = ...)`, it is unaware of this relationship in Java model.

#### 2. **Bidirectional `@ManyToMany` Mapping**

* **Both Entities know** about each other.
* Association is **two-way**.
* One side is the **owning side** (`@JoinTable`), and the other is the **inverse side** (`mappedBy`).
* **Only the owning side** actually updates the **join table** in database.
* In Java memory, both sides need to be manually synchronized.

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

    private String name;

    @ManyToMany
    @JoinTable(
        name = "student_course",
        joinColumns = @JoinColumn(name = "student_id"),
        inverseJoinColumns = @JoinColumn(name = "course_id")
    )
    private List<Course> courses = new ArrayList<>();
}
```

```java
@Entity
public class Course {

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

    private String title;

    @ManyToMany(mappedBy = "courses")
    private List<Student> students = new ArrayList<>();
}
```

#### Generated Database Tables

<table data-full-width="true"><thead><tr><th width="145.296875">Table</th><th width="199.4375">Columns</th><th width="312.31640625">Primary Key</th><th>Foreign Keys</th></tr></thead><tbody><tr><td>student</td><td>id, name</td><td>id</td><td>-</td></tr><tr><td>course</td><td>id, title</td><td>id</td><td>-</td></tr><tr><td>student_course</td><td>student_id, course_id</td><td>(student_id, course_id) composite key</td><td>FK (student_id) → student(id)<br>FK (course_id) → course(id)</td></tr></tbody></table>

* **Same join table structure** as unidirectional.
* But now, **both entities** are aware of the relationship.
* Hibernate still only uses the **owning side** (`Student`) to insert/update/delete rows in the join table.

{% hint style="info" %}
**Fetch Type**

FetchType.LAZY (default) -> Load related entities when accessed.

FetchType.EAGER -> Load related entities immediately.

Best Practice:

* **Keep ManyToMany as LAZY**.
* EAGER loading on large many-to-many relations can explode query size and cause serious performance problems.
  {% endhint %}

{% hint style="info" %}
**Cascade operations**

```java
@ManyToMany(cascade = CascadeType.PERSIST)
private List<Course> courses;
```

But in real-world apps:

* **Cascade cautiously.**
* Usually, you **don’t cascade** on `@ManyToMany` because both sides can exist independently.
  {% endhint %}

{% hint style="info" %}
Owning Side vs Inverse Side

Owning Side -> The entity that defines `@JoinTable` or `@JoinColumn`.

Inverse Side -> The entity with `mappedBy`.

* Only the owning side is responsible for updating the join table.
* The inverse side just reflects the relationship.
  {% endhint %}

## 5. @JoinColumn

### About

* `@JoinColumn` is used to **customize** the **foreign key column** generated for an entity association (like `@OneToOne`, `@ManyToOne`, etc.).
* It defines **how two tables** are **joined** in the database by **explicitly specifying**:
  * The foreign key column name.
  * Referenced primary key column.
* Without `@JoinColumn`, JPA uses **default naming** conventions (which can be confusing or inconsistent).

### Where is `@JoinColumn` Used ?

* It is placed on the **owning side** of relationships:
  * `@OneToOne`
  * `@ManyToOne`
  * (Optionally) in `@OneToMany` + `@JoinColumn` (to avoid a join table)
* Also used in `@JoinTable` (for join table’s joinColumns and inverseJoinColumns).

### Syntax of @JoinColumn

```java
@JoinColumn(
    name = "foreign_key_column_name",
    referencedColumnName = "primary_key_column_name",
    nullable = true/false,
    unique = true/false,
    insertable = true/false,
    updatable = true/false,
    foreignKey = @ForeignKey(name = "fk_constraint_name")
)
```

#### Composite Foreign Keys (Multiple @JoinColumns)

If we need multiple columns (composite foreign key), use `@JoinColumns`:

```java
@ManyToOne
@JoinColumns({
    @JoinColumn(name = "dept_id", referencedColumnName = "id"),
    @JoinColumn(name = "dept_code", referencedColumnName = "code")
})
private Department department;
```

### Important Parameters

<table data-full-width="true"><thead><tr><th width="218.78515625">Parameter</th><th>Meaning</th></tr></thead><tbody><tr><td><code>name</code></td><td>Name of the foreign key column in the owner’s table.</td></tr><tr><td><code>referencedColumnName</code></td><td>Name of the primary key column in the target entity. Default: "id".</td></tr><tr><td><code>nullable</code></td><td>Whether the foreign key can be NULL (default: true).</td></tr><tr><td><code>unique</code></td><td>Whether the foreign key must be UNIQUE.</td></tr><tr><td><code>insertable</code></td><td>Whether the foreign key column is included in SQL INSERT (default: true).</td></tr><tr><td><code>updatable</code></td><td>Whether the foreign key column is included in SQL UPDATE (default: true).</td></tr><tr><td><code>foreignKey</code></td><td>Specifies foreign key constraint name in database.</td></tr></tbody></table>

### Example — `@ManyToOne` with `@JoinColumn`

```java
@Entity
public class Employee {

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

    @ManyToOne
    @JoinColumn(name = "department_id", referencedColumnName = "id")
    private Department department;
}
```

```java
@Entity
public class Department {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String departmentName;
}
```

#### Database Tables Generated:

<table><thead><tr><th width="191.0703125">Table</th><th>Columns</th></tr></thead><tbody><tr><td>department</td><td>id (PK), department_name</td></tr><tr><td>employee</td><td>id (PK), name, department_id (FK to department.id)</td></tr></tbody></table>

* `@JoinColumn(name = "department_id")` tells JPA to create a foreign key column named **department\_id** in **Employee** table.
* It references the **id** column of **Department** table.

If `@JoinColumn` is not given explicitly:

* Hibernate defaults to `<association_property>_<referenced_primary_key>`.
* In above example: `department_id` would still happen automatically — but **being explicit is better for clarity and control**.

### How `@JoinColumn` behaves if missing ?

* JPA will:
  * Generate a foreign key.
  * Guess a column name using entity field name and primary key.
  * Constraint name will be auto-generated.

It is considered **good practice** to **always specify** `@JoinColumn` manually for:

* Database readability.
* Easier migrations.
* Predictable schema.

## 6. @JoinTable

### About

* `@JoinTable` is used to define the **Join Table** (i.e., **intermediate table**)\
  when two entities have a **many-to-many** or sometimes **one-to-many** association.
* A **Join Table** is a separate table that holds **foreign keys** referencing the **primary keys** of the two associated tables.
* `@JoinTable` gives you **full control** over:
  * The name of the intermediate table.
  * The join columns (owner side foreign key).
  * The inverse join columns (other side foreign key).

### Where `@JoinTable` is Used ?

* Mostly in `@ManyToMany` mappings.
* Sometimes in `@OneToMany` (only if you want to manage the relation via a separate table instead of a foreign key directly).

### Syntax of @JoinTable

```java
@JoinTable(
    name = "join_table_name",
    joinColumns = @JoinColumn(name = "owning_entity_foreign_key"),
    inverseJoinColumns = @JoinColumn(name = "inverse_entity_foreign_key")
)
```

### Parameters

<table data-full-width="true"><thead><tr><th width="217.94921875">Parameter</th><th>Meaning</th></tr></thead><tbody><tr><td><code>name</code></td><td>Name of the join table in DB.</td></tr><tr><td><code>joinColumns</code></td><td>Specifies the column that refers to the current (owning) entity’s primary key.</td></tr><tr><td><code>inverseJoinColumns</code></td><td>Specifies the column that refers to the other (inverse) entity’s primary key.</td></tr><tr><td><code>uniqueConstraints</code></td><td>Optional. Defines uniqueness constraints on join table columns.</td></tr><tr><td><code>indexes</code></td><td>Optional. Allows creating indexes on join table columns.</td></tr></tbody></table>

### Example — `@ManyToMany` using `@JoinTable`

Suppose we have two entities:

* **Employee**
* **Project**

An employee can work on multiple projects,\
and a project can have multiple employees.

#### Entity Classes:

```java
@Entity
public class Employee {

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

    @ManyToMany
    @JoinTable(
        name = "employee_project",
        joinColumns = @JoinColumn(name = "employee_id"),
        inverseJoinColumns = @JoinColumn(name = "project_id")
    )
    private List<Project> projects;
}
```

```java
@Entity
public class Project {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long id;
    
    private String projectName;
}
```

#### Database Structure Generated

<table><thead><tr><th width="214.06640625">Table</th><th>Columns</th></tr></thead><tbody><tr><td>employee</td><td>id (PK), name</td></tr><tr><td>project</td><td>id (PK), project_name</td></tr><tr><td>employee_project</td><td>employee_id (FK to employee.id), project_id (FK to project.id)</td></tr></tbody></table>

The `employee_project` table acts as a bridge table — **no direct foreign key inside `employee` or `project` tables**.

### Ownership in @JoinTable

* The entity where `@JoinTable` is defined is the **owning side**.
* The other entity is **inverse side** (no control over join table).

In example above:

* **Employee** owns the relationship.
* **Project** does not.


---

# Agent Instructions
This documentation is published with GitBook. GitBook is the documentation platform designed so that both humans and AI agents can read, navigate, and reason over technical content effectively. Learn more at gitbook.com.

## Querying This Documentation
If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://www.pranaypourkar.co.in/the-programmers-guide/spring/spring-features/spring-persistence/jpa-java-persistence-api/orm-mapping-annotations/3.-relationship-mappings.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
