In which case do you use the JPA @JoinTable annotation? In which case do you use the JPA @JoinTable annotation? java java

In which case do you use the JPA @JoinTable annotation?


EDIT 2017-04-29: As pointed to by some of the commenters, the JoinTable example does not need the mappedBy annotation attribute. In fact, recent versions of Hibernate refuse to start up by printing the following error:

org.hibernate.AnnotationException:    Associations marked as mappedBy must not define database mappings    like @JoinTable or @JoinColumn

Let's pretend that you have an entity named Project and another entity named Task and each project can have many tasks.

You can design the database schema for this scenario in two ways.

The first solution is to create a table named Project and another table named Task and add a foreign key column to the task table named project_id:

Project      Task-------      ----id           idname         name             project_id

This way, it will be possible to determine the project for each row in the task table. If you use this approach, in your entity classes you won't need a join table:

@Entitypublic class Project {   @OneToMany(mappedBy = "project")   private Collection<Task> tasks;}@Entitypublic class Task {   @ManyToOne   private Project project;}

The other solution is to use a third table, e.g. Project_Tasks, and store the relationship between projects and tasks in that table:

Project      Task      Project_Tasks-------      ----      -------------id           id        project_idname         name      task_id

The Project_Tasks table is called a "Join Table". To implement this second solution in JPA you need to use the @JoinTable annotation. For example, in order to implement a uni-directional one-to-many association, we can define our entities as such:

Project entity:

@Entitypublic class Project {    @Id    @GeneratedValue    private Long pid;    private String name;    @JoinTable    @OneToMany    private List<Task> tasks;    public Long getPid() {        return pid;    }    public void setPid(Long pid) {        this.pid = pid;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }    public List<Task> getTasks() {        return tasks;    }    public void setTasks(List<Task> tasks) {        this.tasks = tasks;    }}

Task entity:

@Entitypublic class Task {    @Id    @GeneratedValue    private Long tid;    private String name;    public Long getTid() {        return tid;    }    public void setTid(Long tid) {        this.tid = tid;    }    public String getName() {        return name;    }    public void setName(String name) {        this.name = name;    }}

This will create the following database structure:

ER Diagram 1

The @JoinTable annotation also lets you customize various aspects of the join table. For example, had we annotated the tasks property like this:

@JoinTable(        name = "MY_JT",        joinColumns = @JoinColumn(                name = "PROJ_ID",                referencedColumnName = "PID"        ),        inverseJoinColumns = @JoinColumn(                name = "TASK_ID",                referencedColumnName = "TID"        ))@OneToManyprivate List<Task> tasks;

The resulting database would have become:

ER Diagram 2

Finally, if you want to create a schema for a many-to-many association, using a join table is the only available solution.


It's the only solution to map a ManyToMany association : you need a join table between the two entities tables to map the association.

It's also used for OneToMany (usually unidirectional) associations when you don't want to add a foreign key in the table of the many side and thus keep it independent of the one side.

Search for @JoinTable in the hibernate documentation for explanations and examples.


It's also cleaner to use @JoinTable when an Entity could be the child in several parent/child relationships with different types of parents. To follow up with Behrang's example, imagine a Task can be the child of Project, Person, Department, Study, and Process.

Should the task table have 5 nullable foreign key fields? I think not...