The entity bean relationships

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.

Mapping with the @OneToOne annotation

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.

Mapping with the @OneToMany annotation

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.

Mapping with the @ManyToOne annotation

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.

Mapping with the @ManyToMany annotation

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.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.191.234.150