Synchronization Methods for Many-To-Many Associations

The many-to-many association is a common thing in data modeling. In JPA entities, it is implemented as collections that store associated entities from the other side of the association. To keep collections consistent on both sides, developers usually implement data synchronization methods. This article will highlight common issues that happen when adding synchronized methods for many-to-many bidirectional associations in JPA entities.

Many-To-Many Bidirectional Associations: Why Synchronize?

Before speaking about sync methods, let's look at bidirectional associations and their implementation in JPA in detail. Imagine a blog application where we can mark every post with several tags. We can make two JPA entities for this application: Post and Tag with appropriate attributes like ID, text, etc. Now we need to establish the association between one post and many tags. To do this, let's define a tags attribute on the Post entity, the type of this attribute is Set<Tag>. Notice that each tag can be reused for more than one post. In this case, we can create the posts attribute of type Set<Post> in the Tag entity. This is the bidirectional many-to-many association: we have references to several entities on both sides of the association. And now, our data model looks like this:

Why Set Is Better Than List in @ManyToMany

In this article, we'll highlight the performance penalties involves by using List or Set in @ManyToMany relationships. We use Spring Data JPA with the default persistence provider, therefore with Hibernate JPA.

First of all, keep in mind that Hibernate deals with @ManyToMany relationships as two unidirectional @OneToMany associations. The owner-side and the child-side (the junction table) represents one unidirectional @OneToMany association. On the other hand, the non-owner-side and the child-side (the junction table) represent another unidirectional @OneToMany association. Each association relies on a foreign key stored in the junction table.