JPA Pitfalls (2): List or Set Relationship

This blog article is part of a “series of blog articles” about common pitfalls using JPA and ways to avoid them. In this article, we describe the difference between a set or list relationship.

JPA supports two annotations to specify the order of a collection valued relationship: @OrderBy and @OrderColumn.

You should use the @OrderBy annotation if the ordering is determined by one or more attributes of the element type of the collection. In the following example a department has a list of employees and this list should be retrieved ordered by the employee’s lastname in ascending order and then by the firstname in ascending order.

@OneToMany(mappedBy="department)
@OrderBy("lastname ASC, firstname ASC")
private List<Employee> employees;

By default the relationship is ordered by the primary key.

The @OrderColumn annotation supports maintaining the persistent order of a list relationship in the database. In this case the order does not depend on any attributes of the elements in the list. Instead the order of the list in memory is persistent. Using the @OrderColumn annotation generates an additional index column in the database. A change of the order of elements in the list relationship (includieng insertion and deletion) of elements results in a database update of the index column. This might effect multiple rows in the relationship table. E.g. inserting an employee in the middle of the list causes index calculations for all the remaining instances in the list.

@OneToMany(mappedBy="department)
@OrderColumn
private List<Employee> employees;

If the order of the elements in the relationship is not important (and if duplicates are not needed), it is better to use a set relationship instead, to avoid the index maintenance in the database:

@OneToMany(mappedBy="department)
private Set<Employee> employees;

Recommendation: use a set relationship if there is no requirement for ordering and for duplicates in the domain model.

You can find an example of this pitfall and its solution in the class ListVersusSetExperiment in this project: https://github.com/akquinet/jpapitfalls.git.