JPA: Determining the Owning Side of a Relationship
When using the Java Persistence API (JPA) it is often necessary to create relationships between two entities. These relationships are defined within the data model (think database) through the use of foreign keys and within our object model (think Java) using annotations to indicate associations. When defining relationships or associations within the object model a common task is identifying the owning side of the relationship. Identifying the owning entity within a relationship is important because the owning side is most often, if not always, where the @JoinColumn annotation must be specified. To illustrate the concept of the owning side of an entity we will use a data model to support this discussion.
Let’s analyze this simple model, which depicts a relationship between two tables POST and SERIES. In this relationship, the POST table stores a blog post, which can be part of a series of posts represented by the SERIES table. In the data model, the SERIES_ID foreign key on the POST table associates the POST with its respective SERIES. This foreign key indicates which entity owns the relationship. Let’s add these entities in the object model and establish a simple unidirectional relationship between them. First, the series entity:
@Entity @Table(name="SERIES") public class Series { @Id @GeneratedValue(strategy=GenerationType.AUTO) @Column(name="SERIES_ID") private Integer seriesId; @Column(name="TITLE") private String title; //Accessors... }
And the Post entity:
@Entity @Table(name="POST") public class Post { @Id @GeneratedValue(strategy=GenerationType.AUTO) @Column(name="POST_ID") Integer postId; @Column(name="TITLE") String title; @Column(name="POST_DATE") Date postDate; @ManyToOne @JoinColumn(name="SERIES_ID") private Series series; //Accessors... }
In the Post entity the @JoinColumn annotation is specified above the field Series to denote the foreign key to be used to identify a Post’s respective Series. The @JoinColumn annotation was placed on the Post entity because it is the owning entity in the relationship. The owning side of the entity was determined by referencing both entities in the data model and identifying the entity containing the foreign key. If the relationship between the Post and Series entities was required to be bidirectional, meaning the Post entities should be accessible from the Series, the inverse side of the relationship (Series) must be annotated with @OneToMany, with a mappedBy element defined. The mappedBy element should point to the field on the owning side of the relationship (Post) that specifies the @JoinColumn used to associate the entities.
The mapping for establishing a bidirectional relationship is highlighted in the following refactoring of the Series entity:
@Entity @Table(name="SERIES") public class Series { @Id @GeneratedValue(strategy=GenerationType.AUTO) @Column(name="SERIES_ID") private Integer seriesId; @Column(name="TITLE") private String title; @OneToMany(mappedBy="series") private List posts = new ArrayList(); //Accessors... }
In summary, when determining the owning entity within a relationship defined within a JPA persistence unit, it is important to consult the data model to find which entities respective table in the data model contains the foreign key.
thank you for this clear and short post!
“…If the relationship between the Post and Series entities was required to be bidirectional” was crucial for me here, now I have the whole picture.
“If the relationship between the Post and Series entities was required to be bidirectional” can you please elaborate and tell me this in simple English.
I didn’t get this as well:
“The owning side of the entity was determined by referencing both entities in the data model and identifying the entity containing the foreign key. If the relationship between the Post and Series entities was required to be bidirectional, meaning the Post entities should be accessible from the Series, the inverse side of the relationship (Series) must be annotated with @OneToMany, with a mappedBy element defined”
I got it what you explained. But could you please tell me that which side of entity contains the
CascadeType property and why?
thanx in advance.