To close out this chapter, this section discusses the entity bean relationships. The entity beans are allowed to link to other entities through a single value or collection references. The relationships can be bidirectional or unidirectional.
We will cover the more advanced examples of the entity relationship, including the differences between unidirectional and bidirectional, in the next chapter.
The @javax.persistence.OneToOne
relationship is a direct association between one entity bean and another. The relationship can be expressed at either one or both entities. If each of the entities can refer to the other, then the relationship is bidirectional, otherwise, it is a unidirectional relationship.
By default all the relationships in the Java programming language are unidirectional. In order to establish bidirectional annotations, metadata must also apply to the other entity in order to create an inverse relationship.
In the relational databases, the inverse relationship always exists, and can be inferred through the relational data model.
A simple example of the use of the @OneToOne
annotation with entities is as follows:
@Entity public class Address implements java.io.Serializable { @Id @Column("ADDRESS_ID") private int addressId; /* ... */ } @Entity public class Employee implements java.io.Serializable { @Id @Column(name = "EMP_ID") private int employeeId; @OneToOne @JoinColumn(name = "EMPLOYEE_ADDRESS_FK", referencedColumnName = "ADDRESS_ID") private Address address; /* ... */ }
Here we have two entities, Employee
and Address
, and we defined a unidirectional association, a one-to-one relationship, between an Employee
instance and an Address
instance expressed in the Java programming language. Employee
has a reference to Address
, but the Address
instance has no information about the Employee
instance.
In order to define an entity relationship more succinctly, we introduce a new annotation @javax.persistence.JoinColumn
. This annotation specifies the target database column for joining an entity association to another, or it specifies the persistence collection.
In the resultant employee database table EMPLOYEE
, there is a foreign key column named EMPLOYEE_ADDRESS_FK
that contains the values from the database table column ADDRESS.ADDRESS_ID
.
The @javax.persistence.OneToMany
annotation expresses an entity that can be related to multiple instances of another entity type. The @OneToMany
relationship is added to a java.util.Collection
field variable.
In a unidirectional relationship, the target entity of the one-to-many relationship does not maintain a single value reference back to the source entity.
In a bidirectional relationship, the target entity of the one-to-many relationship does maintain a single value reference pointing back to the source entity.
Let us look at an example of a @OneToMany
entity relationship. The following code defines a project entity that owns a collection of the task entities:
@Entity public class Project implements java.io.Serializable { /* ... */ @OneToMany private Collection<Task> tasks; public Collection<Task> getTasks() {return tasks;} public void setTasks(Collection<Task> tasks) { this.tasks = tasks; } /* ... */ } @Entity public class Task implements java.io.Serializable { @Id @Column(name = "TASK_ID") private int id private int length; private String title; private Description; /* ... */ }
The preceding code shows that the entity Project
references a collection of the entity Task
. There is no inverse relationship, because the entity Task
does not reference the entity Project
. The entity Project
is the owner of the one-to-many relationship.
The ORM provider, following the rules of the JPA specification, applies the mapping so that the entity Project
is mapped to the target database table named PROJECT
. The entity Task
is mapped to the database table named TASK
. The provider maps the association to a join table named PROJECT_TASK
, which has two foreign key columns: a foreign key that maps to the unique rows in the table PROJECT
and the other foreign key column that maps to the unique rows in the table TASK
. The foreign key columns are the same type as the reference source and target entities, respectively.
The @javax.persistence.ManyToOne
annotation expresses the entity relationship of multiple instances of entities being associated to one entity. This relationship is the polar opposite of the @OneToMany
relationship.
In a unidirectional relationship, the target entity of a many-to-one relationship does not have a collection of references pointing back to the source entities.
In a bidirectional relationship, the target entity of a many-to-one relationship does maintain a collection of references pointing back to the source entities.
Let us look at an example of a @ManyToOne
entity relationship. The following code defines the relationship where multiple employee entities share a security clearance entity instance.
@Entity public class Employee implements java.io.Serializable { /* ... */ @ManyToOne private Clearance clearance; public Clearance getClearance() {return clearance;} public void setClearance(Clearance clearance) { this.clearance = clearance; } } @Entity public class Clearance implements java.io.Serializable { @Id private int securityId; private String securityLevel; /* ... */ }
Here we have two entities Employee
and Clearance
, and we defined a unidirectional many-to-one association between multiple Employee
instances and a Clearance
instance expressed in the Java programming language. Zero or more Employee
instances defines a reference to a shared Clearance
instance, but the Clearance
instance has no information about any of the Employee
instances.
Under the rules of the JPA specification, the entity Employee
is mapped to the target database table named EMPLOYEE
. The entity Clearance
is mapped to a table named CLEARANCE
. The table EMPLOYEE
contains a foreign key column to the table CLEARANCE
. The JPA provider will create a foreign column named CLEARANCE_SECURITY_ID
, because SECURITY_ID
is the mapped primary key column of the target entity, which in this case is the entity Clearance
. The foreign key column is the same type as the primary key column in the target entity.
The @javax.persistence.ManyToMany
annotation expresses the entity relationship of multiple instances of entities being associated to multiple instances of the other entity type. The annotation @ManyToMany
is placed on a java.util.Collection
field value or the property accessor of the source entity bean.
In a unidirectional relationship, the target entities of a many-to-many relationship do not have a collection of references pointing back to the source entities.
In a bidirectional relationship, the target entities of a many-to-many relationship do maintain a collection of references pointing back to the source entities.
The many-to-many relationships can be split into two relationships usually, the one-to-many and many-to-one relationship between the two entities. This procedure typically applies to the logical and physical data modeling in the database, and also at the conceptual level.
Here is an example of the many-to-many relationship that associates many products to the invoices. A product can be a part of an invoice; many products go to make one invoice. An invoice usually has products that a customer has ordered; an invoice has many products.
@Entity public class Product implements java.io.Serializable { @Id @Column("PROD_ID") private int id; @Column("PROD_NAME") private String name; @ManyToMany private Collection<Invoice> invoices; public Collection<Invoice> getInvoices() { return invoices; } public void setInvoices(Collection<Invoice> invoices) { this.invoices = invoices; } /* ... */ } @Entity public class Invoice implements java.io.Serializable { @Id @Column("INV_ID") private int id; @Column("INV_NAME") @Temporal(Temporal.DATE) private Date name; @ManyToMany(mappedBy = "invoices") private Collection<Product> product; public Collection<Product> getProducts() { return product; } public void setProducts(Collection<Product> product) { this.product = product; } /* ... */ }
This code represents a bidirectional many-to-many relationship. We have two entities, Product
and Invoice
. The entity Product
references a collection of entities type Invoice
. The entity Invoice
references a collection of entities Product
.
Each entity defines an annotation of the collection. The many-to-many annotation of the products inside the Invoice
entity uses the mappedBy
argument to establish the owner of the relationship. The owner of the relationship is Product
. By specifying the mappedBy
attribute, we allow the mapping information to be shared in both directions for the relationship.
Given this example, the JPA provider maps the source entity Product
to the database table named PRODUCT
. It maps the target entity Invoice
to the database table named INVOICE
. It creates a join table with the conjugation named PRODUCT_INVOICE
. It will have two foreign key columns.
The JPA provider will create a foreign column in the join table named INVOICE_PROD_ID
, because PROD_ID
is the mapped primary key column of the target entity, which in this case is the entity INVOICE
. The foreign key column is the same type as the primary key column in the target entity.
The JPA provider will create a foreign column in the join table named PRODUCT_INV_ID
, because INV_ID
is the mapped primary key column of the target entity, which in this case is the entity named PRODUCT
. The foreign key column is the same type as the primary key column in the target entity.
It is possible to create a unidirectional many-to-many relationship too, but in this case we need to explicitly define a join table.
18.191.234.150