Sei sulla pagina 1di 9

JPA 2 | Understanding relationships between entities

Entities in Object Relational Model are the objects that contain/maintain state for the
application. An application can have relationships between its objects. For example,
an author can have one or many books to his name. Or an employee can work for
one or more projects. We find relationships everywhere. For a relationship, we need
two entities that can be related to each other, just like in a marriage. Entities need to
have
a
relationship
with
other
entities
to
become
meaningful.
In today's blog, we will look at how entity relationships are defined in JPA 2. The
ideas and most of the contents on this blog are inspired from Pro JPA 2 : Mastering
the
Java
Persistence
API .
A

relationship

normally

has

the

following

attributes

Role : In every relationship there are two entities that are related to one
another, and each entity is said to play arole in the relationship.
Direction : Relationships can be unidirectional or bidirectional. For e.g.. a
Person has an address is normally unidirectional whereas Employee working on a
project is normally bidirectional. We will look at how to identify and define
directionality while coming up with a Data Model.
Cardinality : Cardinality defines the number of entities that exists on each
side of the relationship. For e.g. a Person could have written many books. In such a
case the cardinality on the source side of the relationship (the side that is used to
traverse the relationship) is one where as the cardinality on the destination side of
the relationship is "many". We will see later in the post that cardinality is what drives
the relationship to a great extent.
Ordinality : Ordinality determines whether the target entity needs to be
specified when a source entity is created. Ordinality thus boils down to Yes or No,
True or False, 0 or 1.

Mappings in JPA 2
Mappings or associations in JPA 2 are divided into two broader groups :

Single Valued Mappings -> A mapping from source entity to target entity
where the cardinality of the target entity is "one". OneToOne and ManyToOne are
examples of Single Valued mappings.

Collection valued Mappings -> A mapping from source entity to destination


entity where the cardinality of the target entity is more than
one. OneToMany and ManyToMany are examples of Collection Valued mappings.

Single Valued Mappings


In a single valued entity, the source entity refers to at most one target entity. JPA
uses two annotations to define the Single Valued Mappings : @ManyToOne and
@OneToOne. We will understand each one of them in turn.

@ManyToOne Mapping
A Many to one mapping occurs when many entities on the source side of the
relationship( the side from which the relationship is traversed ) are related to a single
entity on the target side of the relationship. For e.g. Many Employees can be
associated with a single department. Thus Employee is the "many" from ManyToOne
annotation and Department is the "one" from the same annotation. Here is the
example
figure
straight
from
the
Pro
JPA
2
Book:

The important thing to notice in the above figure is that the arrow head points from
Employee to Department and not the other way round. This type of relationship is
called Unidirectional
Relationship.
A Unidirectional many to one relationships in JPA2 is defined by simply annotating
the attribute in the Source Entity that refers to the target entity with @ManyToOne
annotation.
The example below shows the Employee Entity that has a
Unidirectional ManyToOne association with the Department Entity.

@Entity
public class Employee {
@ManyToOne

private Department department;


// other attributes defined.....
}

@JoinColumn
A Join Column in JPA is a column in the owner entity that refers to a key (usually a primary
key) in the non-owner or inverse entity. The first thing that comes to mind after reading the
above line is that JoinColumns are nothing but a Foreign Key Columns. And it is indeed the
case. JPA calls them Join Columns, possibly because they are more verbose in what their
actual

role

is,

to

join

the

two

entities

using

common

column.

Another thing to notice above is that we have used the terms owner and non-owner entities.
For easy rememberability, the entity that has a join column is always the owning entity.

In the above example, the owner Entity Employee, has a Join Column named DEPT_ID that
has

foreign

key

to

the

non-owner

Department

entity.

ManyToOne and JoinColumns


ManyToOne mappings are always defined on the owning entity. Thus for the above figure the
Entity Class would look like this :

@Entity
public class Employee {
@Id private int id;
@ManyToOne
@JoinColumn(name="DEPT_ID")
private Department department;

// ...
}
Note that if no @JoinColumn is defined along with the @ManyToOne mapping, then a
default name is assumed. The default name is composed of the name of the relationship
attribute in the source entity (which is department in our case) + an underscore + the name
of the primary key on the target entity (which in our case is id) . Thus the default name would
be department_id (assuming case insensitiveness).

OneToOne Mappings
A person can have only one full time job (in normal scenarios). In such a case the
relationship between a person and his job is a OneToOne relationship. Thus we will define
the one to one mapping between Person and his Job as follows :

@Entity
public class Person {
@Id private int id;
@OneToOne
@JoinColumn(name="JOB_ID")
private Job job;
// ...
}
Notice how similar the mapping is to the previous ManyToOne mapping. The attribute job
has a OneToOne mapping annotation as well as the JoinColumn annotation that identifies
the name of the column that maps to the key in the target column.
In OneToOne mapping one instance of source entity can refer to only one instance of target
entity.

Bidirectional

OneToOne

Mapping

The above example depicts a unidirectional OneToOne mapping. There are cases when the
relationship is bidirectional. For e.g. in the above case the target entity Job also can have an
association to the Person whom this job belongs to. In such a case, it is a bidirectional
OntToOne relationship. We know that the owner always have a JoinColumn annotation. In
the case of OneToOne mapping, any entity can be the owner. The other non-owner entity
then has to provide the mappedBy attribute value to indicate that it is not the owner of the
relationship.

@Entity public class Job { @Id private int id; private


String
designation;
private
String
location;
@OneToOne(mappedBy="job") private Person person; // ... }
In the above example, the mappedBy attribute refers to the attribute name job, defined in the
source

Collection

entity

Valued

Person.

Mappings

When a source entity(or a collection of source entities) refers to a collection of target entities,
we use collection valued mappings. The two collection valued mapping annotations in JPA
are OneToMany and ManyToMany.

OneToMany

mapping

When a source entity is associated with a collection of target entities, the relationship defined
is a one to many relationship. For example, while reading an ebook you can define multiple
bookmarks. The relationship between a Book and its associated Bookmarks is a One To
Many

relationship.

@Entity
public class Book {
@Id private int id;
@OneToMany
@JoinColumn(name="BOOK_ID") // BOOK_ID exists in the
BookMark table
private List bookMarks;
// ...
}
The above example depicts a Unidirectional OneToMany relationship between Book and its
bookmarks.

Bidirectional

OneToMany

Mapping

When the relationship is bidirectional, there are normally two associations defined : one from
source to target entity(having the JoinColumn annotation) , and the other from target to
source entity(having the mapped by attribute ). OneToMany bidirectional mapping always
implies a ManyToOne mapping back to the source. Another important thing to remember
from the previous discussion about ManyToOne mapping is that if theres is a ManyToOne
mapping, then the JoinColumn annotation will always be defined on the ManyToOne
mapping attribute. Thus in case of Bidirectional OneToMany mapping, the JoinColumn will
exists

on

the

entity

having

ManyToOne

annotation.

@Entity
public class Book {
@Id private int id;
@OneToMany(mappedBy="book")
private List jobs;
// ...
}

@Entity
public class Job {
@Id private int jobId;
@ManyToOne
@JoinColumn(name="book_id")
private Book book;
// ...
}

ManyToMany

Mapping

When a source entity is associated with multiple target entities and the same target entity is
also associated with multiple source entities, then there exists a ManyToMany mapping
between source and target entity. For example, a Person can have multiple club
memberships and each club can also have multiple members. In this case the association
between

Person

and

Club

entity

is

ManyToMany.

Although a Unidirectional ManyToMany does not really have any big takers (if at all), it is still
possible

to

define

it.

Lets

see

an

example.

@Entity
public class Person {
@Id private int id;
@ManyToMany
private List memberOf;
// ...
}

@Entity
public class Club {
@Id private int id;
private String name;
// ...
}
As we can see, the Club entity does not have any ManyToMany mapping to
the
Person
Entity.

Bidirectional ManyToMany Mapping


In the real world, there would exist a bidirectional ManyToMany mapping. And
as we know in a bidirectional mapping, there should be a way to identify the
source
and
target
entity.
We do that by defining the mappedBy attribute of the relationship on the target
entity. Note that since the multiplicity of both the sides of the relationship is
plural, it is not possible(or feasible/correct) to store an iunlimited set of foreign
key values in a single entity row. We should use the third table to associate
the two entities. This third table is called the JoinTable. A Join Table is a
requirement for a ManyToMany relationship. A JoinTable consists of the
Primary Keys from both the entities and nothing else. Here is an example of
ManyToMany relationship from Pro JPA2 book.

In the above example, the Employee and Project table are two entities related
with ManyToMany relationship. EMP_PROJ table is the JoinTable that is used
to
store
the
entity
reference
for
each
of
the
table.
In JPA, we use the @JoinTable annotation to define a Join Table for the Many
to
Many
relationship.
Here
is
an
example

@Entity
public class Employee {
@Id private int id;
private String name;
@ManyToMany
@JoinTable(name="EMP_PROJ",
joinColumns=@JoinColumn(name="EMP_ID"),
inverseJoinColumns=@JoinColumn(name="PROJ_ID"))
private Collection projects;
// ...
}
The JoinTable annotation has a name attribute which corresponds to the name of the Join
Table.

It

also

has

two

other

attributes

joinColumns which is the column name of the owning Entity

inverseJoinColumns which is the column name of the inverse or non owning Entity.

Summary
The blog post above talks about Entity relationships and the JPA specifications to handle
relationships in a consistent manner. Almost the entire stuff was inspired from chapter 4
section 6 of the Pro JPA 2: Mastering the Java Persistence API. I hope after reading this, you
should be able to correctly define and manage JPA entities in your project.

Potrebbero piacerti anche