Skip to content

Relationships

Guillaume Le Cousin edited this page Dec 5, 2021 · 2 revisions

Entity relationships

In a relational database, relationships are done using foreign keys.

Similarly, on Java entities the @ForeignKey annotation represents a foreign key in the database. To represent the relationship on the other side, the @ForeignTable annotation is used.

In addition, the @JoinTable annotation allows to represent a many to many relationship, using an intermediate table to link entities.

Examples for each type of relation is described below in the sub-sections.

The @ForeignKey annotation provides additional information about the behavior of the link:

  • optional (default to false) specifies if the foreign key is nullable
  • onForeignDeleted (possible values are SET_TO_NULL and DELETE, default to DELETE) specifies what to do when the foreign entity is deleted: either to set the foreign key to null, or delete the entities containing the foreign key.
  • cascadeDelete (default to false) specifies if the foreign entity (linked by this foreign key) must be deleted when the entity containing the foreign key is deleted. It can be used together with the Spring annotation @Column to specify the column name.

The @ForeignTable annotation provides additional information about the behavior of the link as well:

  • joinKey must be set to specify which attribute (that must be a @ForeignKey) of the linked entity to use for the link
  • optional (default to true) specifies if at least one foreign entity must always exist

The @JoinTable annotation provides additional information about how to make a many to many relationship:

  • tableName is the intermediate table to use, if not specified it will be automatically generated
  • columnName is the column of the intermediate table to use as a foreign key to the entity containing the @JoinTable annotation. If not specified it will be automatically generated
  • joinProperty is the name of the attribute on the linked entity containing the @JoinTable annotation specifying the other side of the link

One to many

For a one to many relationship, for example between an Author and books:

+--------+          +------+
| Author | 1 ---> n | Book |
+--------+          +------+

A foreign key is present on the Book table to link it to the Author table. In entities it is done using @ForeignKey on the Book entity, and @ForeignTable on Author entity:

@Table
public class Book {
  @Id @GeneratedValue
  private Long id;

  @ForeignKey
  private Author author;
  
  [...]
}

@Table
public class Author {
  @Id @GeneratedValue
  private Long id;
  
  @ForeignTable(joinKey = "author")
  private Set<Book> books;
  
  [...]
}

The annotation @ForeignTable on class Author does not represent any column in the database, but allows to retrieve the books associated with the author directly from the Author entity.

One to one

Here is an example for a one to one relationship, between a Person and a UserAccount, where a UserAccount must be associated with a Person but a Person does not necessarily have a UserAccount:

@Table
public class Person {
  @ForeignTable(joinKey = "person", optional = true)
  private UserAccount account;
  
  [...]
}

@Table
public class UserAccount {
  @ForeignKey(optional = false, onForeignDeleted = OnForeignDeleted.DELETE, cascadeDelete = false)
  private Person person;
  
  [...]
}

Many to many

Here is an example for a many to many relationship, between books and authors, where a book may have several authors, and an author may have written several books:

@Table
public class Book {
  @JoinTable(joinProperty = "books")
  private Set<Author> authors;
  
  [...]
}

@Table
public class Author {
  @JoinTable(joinProperty = "authors")
  private Set<Book> books;
  
  [...]
}

Cascade save and delete

When saving or deleting an entity, the cascade behavior will analyse linked entities to save or delete them as needed. For example on a one to many link between an author and books, if you add new books and remove some books on the author entity, saving the author entity will automatically insert the new books and delete the removed books.

The cascade behavior can be specified on the @ForeignKey and @ForeignTable annotations through the attributes optional, onForeignDeleted and cascadeDelete.

Clone this wiki locally