Up to this point, we’ve considered JPA capabilities for only one table in a database. However, in the real world, we often have to interact with several interconnected entities.

There are four types of connections or relationships between two entities:

  1. One-to-one
  2. One-to-many
  3. Many-to-one
  4. Many-to-many

JPA can manage all these relationships using a number of different types of annotations. In this topic, we will learn about these JPA annotations, and see how they can be applied to entity relationships in your applications.

One-to-One Relationships

Imagine you are developing an application called Tweeter. This application has a table with user logins, as well as a table that contains user details, such as their name, location, and email. When a user logs in, we want to load their information, so we will need to connect these two tables together. In this situation, every single user connects to a single record of user information. This is called a one-to-one relationship since one user record matches one user information record.

To define this relationship, you can use the JPA @OneToOne annotation. This annotation is placed on top of the entity field or property which refers to the associated entity. In addition to using the @OneToOne annotation, we will need to use a @JoinColumn annotation with the "name = " parameter for specifying the mapped column. It allows joining an entity association: such a column connects the User table and the UserDetails table.

@Entity
public class User {

    @Id
    private long id;

    @OneToOne
    @JoinColumn(name = "user_id", nullable = false)
    private UserDetails user_details;

}

@Entity
public class UserDetails {

    private long user_id;

    @Id
    private long user_detail_id;

    private String name;
    private String location;
    private String email;

}

The @JoinColumn annotation on top of the user_details field indicates that the UserDetails table has a user_id foreign key column specifying an entity association between these tables.

The "nullable = false" parameter of the @JoinColumn annotation indicates that the annotated field should not be null.

The User entity has a field UserDetails. In other words, the User entity “knows” about user_details to which it refers. However, the UserDetails entity doesn’t have any fields that would refer to User, so user_details doesn’t “know” to which User it refers. Such a relationship is called unidirectional. A unidirectional relationship has only an owning side, which means the side of a relationship that contains the foreign key in the database.

It is also possible to have a relationship that is bidirectional. In this situation, the User entity “knows” about the UserDetails entity, and UserDetails knows about User. To establish it, we would just need to map user_id in UserDetails back into the User table. We will take a look at bidirectional relationships in more detail when we discuss @ManyToOne relationships later in this topic.

Unidirectional One-to-Many Relationships

In our Tweeter application, we now want to give users the possibility to post tweets. A Tweeter user can post a lot of tweets, and each tweet can be posted by only one user. Such a relationship between the entities User and Tweet is called a one-to-many relationship: one user can post many tweets.

To define the one-to-many relationship between the User and Tweet entities, you can use the JPA @OneToMany annotation. This annotation is placed on top of the entity field or property which refers to the associated entity. As in the @OneToOne case, we will need to use @JoinColumn in order to map the columns between the two entities.

@Entity
public class User {

    @Id
    private long id;

    @OneToMany
    @JoinColumn(name = "user_id", nullable = false)
    private List<Tweet> tweets = new ArrayList<>();
}

@Entity
public class Tweet {

    @Id
    @Column(name = "tweet_id")
    private long id;
}

Bidirectional Many-to-One Relationships

In a bidirectional relationship, the two entities “know” about each other. It means that each entity has a field or property that refers to the other entity. A bidirectional relationship has both an owning side and an inverse side, which is the relationship’s opposite side.

The “many” side is always the owning side of the relationship, which means that the corresponding table contains the foreign key to another side of the relation. In our case, one User has many Tweets, so Tweet is this “many” side, the owning side of the relationship that contains the foreign key, whereas the User is the opposite one.

We can use a many-to-one relationship in the case of a unidirectional relationship, but usually, this type of relationship is applied in order to specify a bidirectional connection. Let’s see how to define a bidirectional relationship between User and Tweet.

The Tweet entity should have a reference to the User entity and vice versa. Let’s define the Tweet entity field that refers to the User entity. We know that Tweet and User have the following relationship: many Tweets can belong to one User (many-to-one relationship), so you can use the @ManyToOne annotation on top of the field to specify such a relationship. In addition to the type of relationship, we should also define a mapped column (user_id column in the Tweet table) for joining an entity association using the @JoinColumn annotation.

@Entity
public class Tweet {

    @Id
    @Column(name = "tweet_id")
    private long id;

    @ManyToOne
    @JoinColumn(name = "user_id")
    private User user;
}

Now we have to define another side of the relationship: the User entity. Once again, many Tweets can belong to one User. In other words, one User has many Tweets. It means that we can define the tweets field with a type of List<Tweet> in the User entity. It helps us to refer to the Tweet entity using the @OneToMany annotation with the "mappedBy = " parameter. This one indicates that the entity on this side (the User entity) is the inverse one of the relationship, and the owner “resides” in the other entity (the Tweet entity).

@Entity
public class User {

    @Id
    private long id;

    @OneToMany(mappedBy = "user")
    private List<Tweet> tweets = new ArrayList<>();

}

The mappedBy = "user" parameter specifies that the Tweet entity has a user field that contains the foreign key to the user table so that we can find all the tweets posted by a specified user.

Conclusion

JPA can manage not just one entity but also a relationship between entities. There are four types of such relationships. However, one-to-many and many-to-one are the most popular types. In this topic, you have learned how to deal with a unidirectional relationship by using the @OneToOne and @JoinColumn annotations. Additionally, we’ve studied the situations in which the relationships are described as one entity being related to another entity, or many entities. Now you also know how to deal with bidirectional relationships by using the @ManyToOne annotation with the "mappedBy = " parameter. This should give you a solid foundation for dealing with entity relationships using JPA. In future topics, we will see how to apply these relationships, as well as delve further into such relationships as many-to-many.

Leave a Reply

Your email address will not be published.