In this article we will look in depth at EJB3 Entity Beans (Entities) as well as the key aspects around entities that a developer will need to know for the Component Developer Exam. We will first focus on what an entity is before we will dive into the all the key aspects of object relational mapping as well as entity relationships. Finally we will look at how it fits into the Tudo List application that we started building in the previous articles, Tutorial: Review of Session Beans for the Component Developer Exam and Tutorial: Review of Message Driven Beans for the Component Developer Exam.

Comparison with EJB 2.x Entity Beans

In EJB 2.x the entity bean component was the source of a great deal of teeth gnashing by developers. Basically it was the same type of artifacts as session beans with all the trappings (i.e. XML deployment descriptor files, the various local or remote interfaces and home interfaces and the bean class itself). You needed to use the same methods create() and findByPrimaryKey() methods or other optional finder methods to access the entity beans as one needed to use for accessing session beans. You also had all the callback methods such as ejbCreate(), ejbLoad(), ejbStore(), ejbRemove(), ejbActivate(), ejbPassivate(), and setEntityContext() that you needed to deal with. All this boilerplate code was heavy and unnecessary. This made entity beans one of the key areas to avoid for most developers who were developing complex applications as it was complex and a drain on precious resources.

Because of the problems with entity beans in the EJB2 specification, there were many lightweight solutions that came out to address the persistence needs of applications without needing an EJB container. There was Hibernate, TopLink and Java Data Objects. The EJB3 specification realized the benefits of this lightweight approach and incorporated it into their approach to the persistence needs with the birth of the Java Persistence API (JPA). The first thing is that JPA does not assume the existence of an EJB container and can even be used in a Java SE (Standard Edition) application. JPA covers both Object/Relational Mapping as well as Queries in its specification. It serves basically as a high level abstraction that sits on top of JDBC. One of the nice aspects of JPA is that if you already know Hibernate or TopLink, there is a JPA implementation that is built on top of these persistence frameworks.

Within the Java Persistence API, all EJBs as well as entities are now plain old java objects (POJOs). In fact, entities can be run outside a container! Due to these radical changes in EJB 3, entities can now be easily reused and easier to test than their EJB 2.x counterparts.

What Are EJB3 Entity Beans (Entities)

EJB3 Entity Beans (Entities) are basically POJOs that must to be persisted; their state is stored outside the application in most cases a relational database. They don’t contain any business logic but they normally contain validation and may be part of the domain model. The operations that are performed on entities are similar to database operations such as querying, updating and deleting as well as the previously mentioned persisting of them.

There are two types of entities that exist. These are related to the entity manager. If an entity instance is managed by an entity manager, it is considered to be an attached by the entity manager. Vice versa, if it is not managed by an entity manager, it is considered to be detached. When the entity is attached, the Entity manager will track state changes to the entity and synchronize the changes with the database when it decides to flush its state.

EJB3 Entity Beans (Entities)

In JPA, any class or POJO (Plain Old Java Object) can be converted to an entity with very few modifications. Below is a listing of an entity that is pulled from the Tudo List application of the Property entity.

Java Code: Example of Entity
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "PROPERTY")
public class Property implements Serializable {

	private static final long serialVersionUID = 3434972458764657217L;

    private String key;
    
    private String value;
    
    @Id
    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

    public String getValue() {
        return value;
    }

    public void setValue(String value) {
        this.value = value;
    }

}
Note how this object is just a simple java bean. It has non-public instance variables, with matching getter and setter methods for access to them. There are only some annotations that identify it as an entity. The @Entity annotation tells the persistence engine that the annotated class, Property, is an entity. The @Table annotation provides the name of the database table. These two annotations sit just above the class definition. There are also property-based as well as field-based annotation that we will show.

Property-Based Annotations

The next annotation to notice is the @Id annotation specifies the primary key of the entity. The id attribute is a primary key candidate. We place this annotation before the corresponding getter method, getKey(). This is property-based annotation. With property-based annotation we place the annotation just before the corresponding getter method. With property-based annotations, the persistence engine will use the getter and setter methods to access and set the entity state. If we were to use field-based annotations, the annotations would be placed just before the variable name. An example of this is shown in the next paragraph

Field-Based Annotations

If we want to avoid using property-based annotations for the different fields of our entity, we have the ability to use field-based annotation. First I will modify the Property class that has property-based annotations to one using field-based annotations. The folowing listing demonstrates this:

Java Code: Example of Entity using field-based annotations
import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name = "PROPERTY")
public class Property implements Serializable {

	private static final long serialVersionUID = 3434972458764657217L;

    @Id
    private String key;
    @Basic
    private String value;
    
    public String getKey() {
        return key;
    }

    public void setKey(String key) {
        this.key = key;
    }

}
Note that now we have placed the primary key @Id annotation immediately before the field declaration. Now all other annotations at the field level must also be field-based annotations. The class level notations don’t change. In the case of field-based annotations the persistence engine will use reflection to access and set the entity state. The persistence engine will ignore the getter and setter methods that are present in the entity. This is demonstrated by the elimination of the getValue() and setValue() from the Property Entity. but they are ignored by the persistence engine. All of the attributes other than the primary key are mapped to a database by default. These are called basic mappings. If an attribute is a Java primitive type or serializable such as String, than basic mapping is used. You can do this explicitly by using the @Basic annotation. In the listing above, we have done this for the value field.

Entity Declaration

The last thing that is required, which is similar to EJBs is the need for a no-arg constructor. Since this java bean is going to be persisted to storage, it is good practice to have it implement java.io.Serializable interface. This is because, in the case it becomes a detached entity, the instance can still be persisted. Note that all of what we have done here with annotations can be equally done with XML deployment descriptors. If you want more information on this, consult your JEE 5 documentation.

Mapping an Entity with Defaults

EJB3 Entity Beans (Entities) can be mapped to almost all relational database. Defaulting is used heavily in the EJB3 specification for describing metadata for entities. For example, the use of the @Table annotation with the name “Property” is superfluous since this is done by default by the persistence engine. This is similar for the mapping of field names to column names. They will exactly match the names defined in your entity. So value in your entity becomes field named VALUE as a column name in the database. Another key issue with defaulting is that for String, the column size will default to VARCHAR(255). To change this you will need to use the length element of the @Column annotation. An example is shown below.

Java Code: Example of @Column Annotation
@Column(name="MIDDLE_NAME", length=55) 
protected String middleName;
Mapping the Entity Table

In order to map the entity table, if you want to override the default, you specify the table using the @Table annotation. There are a number of parameters that you can also set besides the name of the table. They are listed below:
  • name - the name of the table
  • catalog - the catalog of the table (used for organizing the schemas)
  • schema - the schema of the table
  • uniqueConstraints - specify constraints on more than one column


Mapping the Entity Columns

Entity fields or properties’ default column name can be overridden by using the @Column annotation. The properties are listed below:
  • name - the name of the column
  • unique - defines a unique constraint
  • nullable - if the column accepts null values
  • insertable - determines if the column can be used in an INSERT statement
  • updatable - determines if the column can be used in an UPDATE statement
  • columnDefinition - allows you to specify the SQL for creating the column
  • table - name of the table of which the column belongs
  • length - the length of the column
  • precision - the decimal precision of the column
  • scale - the decimal scale of the column


Mapping of Enumerated Data Types

It is possible for you to map enumerated data types that are defined in Java classes by using the @Enumerated annotation. There are two options for using the @Enumerated annotation. The first is to when you have specified an ordinal value type enumerator. This would be used if you have an enumerated values such as the following:

Java Code: Enumerated Type
public enum CaseType (CIVIL, CRIMINAL, IMMIGRATION, EMPLOYMENT);
The values associated with this enumeration will be associated with an index 0 through 4. So CIVIL=0, CRIMINAL=1, etc. In this case the @Enumerated annotation is used in the following manner:

Java Code: Example of @Enumerated - Ordinal Type
@Enumerated(EnumType.ORDINAL)
...
protected CaseType caseType;
If you have defined the enumeration as a String, then using the @Enumerated annotation would be used in the following manner:

Java Code: Example of @Enumerated - String Type
@Enumerated(EnumType.STRING)
...
protected CaseType caseType;
Mapping of Binary or Character Large Objects (BLOBs or CLOBs)

As relational databases are able to store both BLOBs and CLOBS for graphics, there is an annotation, @Lob that can be used to maps this data directly into a field or property of an entity. This is generally used in conjunction with @Basic in order to facilitate loading of the data from the database when it is accessed. An example is shown below:

Java Code: Example of @Lob
@Lob
@Basic(fetch=FetchType.LAZY)
protected byte[] icon;
Mapping of Temporal Types

Another data type that often needs to be mapped to the database is date, a time or timestamp. There is the @Temporal annotation which can be used for this mapping. There is a parameter, TemporalType which if not specified will default to TIMESTAMP. In the example below, we will explicitly provide a data type mapping to DATE.

Java Code: Example of @Temporal using Date Type
@Temporal(TemporalType.DATE)
protected Date lastAccess;
Mapping to Multiple Tables

There are times, especially when an object might have media (i.e. pictures, video or audio) as part of it’s data, when you might need to map an object to multiple tables. An example of this would be a product or an SKU object. In this case, you can use the @SecondaryTable annotation to map data to more than one table.

Tutorial: In Depth Review of EJB3 Entity Beans for the Component Developer Exam-a5-objectmappedto2tables.jpg
Figure: Object Mapped to Two Tables

There are a number of properties that you can use with the @SecondaryTable annotation. They are shown below:
  • name - the name of the table
  • catalog - the catalog of the table (used for organizing the schemas)
  • schema - the schema of the table
  • pkJoinColumns - this provides the link between the primary key and foreign key of the primary and secondary tables being used.
  • uniqueConstraints - specify constraints on more than one column


An example of what this would look like is shown below:

Java Code: Entity mapping to multiple tables
@Entity 
@Table(name="PRODDESC") 
@SecondaryTable(name="PRODMEDIA",
pkJoinColumns=@PrimaryKeyJoinColumn(name="PRODUCT_ID")) 
public class User implements Serializable { 
   ..
}
Entity Identity through Primary Keys

All entities must be uniquely identifiable within the domain model. It is no different from the fact that you must be uniquely identifiable via an ID card or a passport. The primary keys provide this functionality for entities of enabling you to uniquely identify and retrieve a record. Primary keys are used to map one or more properties to the following types:
  • Java primitive type (including wrappers)
  • java.lang.String
  • A class composed of primitives and/or strings.


There are also a number of requirements that a primary key class must meet. These are:
  • The primary key’s setters and getters must be public
  • The primary key getter must be public or protected.
  • The primary key class must have a public default constructor.
  • The primary key class must implement the hashCode() and equals (Object other) methods.
  • The primary key class must be serializable.
  • The composite primary key class must be mapped to a multiple fields or properties of the entity class or to an all of the fields or properties of an entity class.


The simplest means of creating a primary key is to use the @Id annotation to identify one or more properties to uniquely identify the entity. Primary keys are to composed of multiple persistent properties. These are known as composite keys and there are two ways that this can be done.

@IdClass Annotation

In this case, you use a class made up a multiple properties to provide a unique identifier for the entity. The primary key class must meet the following requirements:
  • It must implement java.io.Serializable.
  • It must have a public no-arg construction.
  • It must implement the equals() and hashcode() methods.


An example is shown below:

Java Code: Example of Primary Key Class
import java.io.Serializable; 
public class UnitLoadDevicePK implements Serializable
{
   private static final long serialVersionUID = 1L; 
   private String flightName; 
   private Long flightNumber;
   public String getFlightName() { 
      return flightName; 
   } 
   public void setFlightName(String flightName) { 
      this. flightName = flightName; 
   } 
   public Long getFlightNumber() { 
      return flightNumber; 
   } 
   public void setFlightNumber(Long flightNumber) { 
      this. flightNumber = flightNumber; 
   }

   @Override 
   public int hashCode(){ 
      ...
    }

   @Override 
   public boolean equals(Object obj) { 
      ...
   }
}
The entity bean, in this case the Cargo bean, must have the same properties as the primary key class. This class must have multiple @Id annotations:

Java Code: Entity with Primary Key Class
import javax.persistence.Entity; 
import javax.persistence.Id; 
import javax.persistence.IdClass;

@Entity
@IdClass(UnitLoadDevicePK.class)
// Use a composite primary key using a custom PK class 
public class UnitLoadDevice
{
   @Id
   private String flightName;
   @Id
   private Long flightNumber;
 ...
}
@EmbeddedId Annotation

The other way to define primary-key class and composite keys is to embed the primary-key class directly in the bean. This annotation is used for doing this in conjunction with the @Embeddable annotation. The @Embeddable class is the type for the primary key and the property is marked with the @EmbeddedId. An example is shown below:

Java Code: Example of @EmbeddedId Primary Key
import java.io.Serializable;
import javax.persistence.Column; 
import javax.persistence.Embeddable; 
import javax.persistence.EmbeddedId;

@Embeddable
// Flag to JPA that we're intended to be embedded into an Entity 
// class as a PK 
public class EmbeddedUnitLoadDevicePK implements Serializable
{
   private static final long serialVersionUID = 1498L;
   @Column
   private String flightName;
   @Column
   private Long flightNumber;
   public String getFlightName() { 
      return lastName; 
   } 
   public void setFlightName(String flightName) { 
      this. flightName = flightName; 
   } 
   public Long getFlightNumber() { 
      return flightNumber; 
    } 
   public void setFlightNumber(Long flightNumber) { 
      this. flightNumber = flightNumber; 
   }
   @Override 
   public int hashCode() { 
      ... 
   } 
   @Override 
   public boolean equals(Object obj) { 
      ... 
   }
Then we can have the UnitLoadDevice bean class to use the EmbeddedUnitLoadDevicePK directly with the @EmbeddedId annotation:

Java Code: Example of Entity with @EmbeddedId
@Entity
public class UnitLoadDevice
{
   @EmbeddedId
   private EmbeddedUnitLoadDevicePK id;
   ...
}
And now we are free to use the the primary-key class to fetch the entity. The way to do this is by using EntityManager method for find() or getReference() using the primary-key class to identify the entity:

Java Code: Fetching entity using embeddedId Primary Key
 EmbeddedUnitLoadDevicePK pk = new EmbeddedUnitLoadDevicePK();
pk.setFlightName(“AirFrance”);
pk.setFlightNumber(“103E”);
// Then look up the unit load device using the primary key
UnitLoadDevice uld = em.find(UnitLoadDevice.class, pk);
Primary keys can be generated manually or they can be generated by the persistence provider. There are situations where a primary key In the next section, we will look at persistence provider generated keys.

Generating Primary Keys

In many cases, rather than have the application provide a means of supplying a primary key, it is preferred to use automatically generated primary keys. There are a number of strategies for doing this. These strategies are:

Table Strategy - In this strategy, the persistence engine will use a relational database table for generating primary key values. An example of this strategy for the Todo entity is given below:

Java Code: Table Strategy generated primary key
@TableGenerator(name="TODO_SEQ", 
				table="SEQUENCE_TABLE",
				pkColumnName="SEQUENCE_NAME", 
				valueColumnName="SEQUENCE_COUNT")

@Id 
@GeneratedValue(strategy=GenerationType.TABLE,
			generator="TODO_SEQ") 

public int getId() { return id; }
Note how we have used the @TableGenerator annotation on the primary key attribute here to specify the table used for key generation. It is also possible to use this on the entity class. There are defaults for these elements but they are always dependent of the persistence engine of the supplier. Check their documentation for more information. Based on our example above, the elements are outlined below:
  • The name element for the generator is TODO_SEQ.
  • The table element, SEQUENCE_TABLE is the table name that is used for storing the generated values. We could use the default table element which is dependent on the persistence engine that is employed.
  • The pkColumnName element is SEQUENCE_NAME. This is the primary key column.
  • The valueColumnName element is SEQUENCE_COUNT. This column is for storing the last key value generated.
  • The @GeneratedValue annotation indicates the we are using the TABLE strategy for the key generation strategy. The default strategy is AUTO. The @GeneratedValue annotation can be either a field-based or property-based annotation.


Sequence Strategy

This strategy is useful for relational databases that have their own built in mechanism called sequences for generating key such as Oracle. To take advantage of this functionality, we use the @SequenceGenerator annotation to invoke the sequence we need to use. An example is shown below:

Java Code: Sequence Strategy example
@SequenceGenerator(name="TODO_SEQ", 
				sequenceName="TODO_SEQUENCE")
The elements for using the sequence strategy are outlined below:
  • The name element is used to identify the generator.
  • The sequenceName element is used to identify the database sequence object.
  • The initialValue element is the initial value assigned to the primary key sequence. The default is equal to 1.
  • The allocationSize is the cache size used for the sequence. This is read by the persistence engine to obtain the sequence. The default value is 50.
  • The @SequenceGenerator annotation can be either a field-based or property based annotation. As well you can place it on the entity class.
  • The @GeneratedValue annotation indicates here that we are using the sequence generation strategy. The @GeneratedValue annotation can be either a field-based or property-based annotation. In this case, it would look like the following:

    Java Code: Example of @GeneratedValue
    @Id 
    @GeneratedValue(strategy=GenerationType.SEQUENCE,
    						generator="TODO_SEQ")


Here the SEQUENCE strategy is specified and TODO_SEQ is the name of the primary key generator. This must match the name element of the @SequenceGenerator annotation.

Identity Strategy

If the database uses an identity column for generating keys, we can then use this to specifiy an IDENTITY strategy. This type of key generation is used by Microsoft SQL Server. We use the @GeneratedValue annotation to apply this the IDENTITY strategy.

Java Code: Example of Identity Strategy
@GeneratedValue(strategy=GenerationType.IDENTITY)
Auto Strategy

The last strategy is the AUTO strategy. In this case you leave it to the persistence engine to select the strategy. Each application server supplier in providing a persistence engine will choose the strategy that best aligns with their interests. If you want to specify the AUTO strategy explicitly, it is done in the following manner:

Java Code: Example of Auto Strategy
@GeneratedValue(strategy=GenerationType.AUTO)
You can do it implicitly as well in the following manner:

Java Code: Example of Default Auto Strategy
@GeneratedValue
How to Override Metadata Defaults

This is relatively straightforward and we hinted at this in the Property entity. Note how we overrode the default for the table name by adding the @Table annotation. You also can do the same for the fields through the @Column annotation as shown in the following excerpt for the User entity of the Tudo List application:
Java Code: Metadata default override
@Column(name = "FIRST_NAME") 
public String getFirstname() { return firstName; } 
public void setFirstname(String firstName) {
this.firstName = firstName;
}
Defining Transient Fields

There are times when you don’t want a particular entity field to be persisted into permanent storage. In this case, you can use the @Transient annotation to ensure that it doesn’t get saved. Transient fields tend to be used primarily for caching of data. You could use a transient value in the following manner:

Java Code: Transient Field Definition
@Entity
public class Todo {
....
@Transient
protected Long activeTodoCount
...
public Long getActiveTodoCount(){
	return activeTodoCount;
}

public void setActiveTodoCount(Long activeTodoCount){
	this.activeTodoCount = activeTodoCount;
}
This can also be achieved in the following manner:

Java Code: Declaration of transient variable
 transient public Long activeTodoCount;
Below is a table of data types that are readily persisted into a database. Of course this is restricted by the type of data that can be readily held in a relational database.

Tutorial: In Depth Review of EJB3 Entity Beans for the Component Developer Exam-a5-datatypetable.jpg
Table: Allowable Data Types for Persistence

Object/Relational Mapping
There are many challenges to mapping objects to a relational database. This is because the way relationships are established in an object oriented language such as java differ significantly from how relationships are done in a relational database. Java uses features such as inheritance, polymorphism, references as well as methods to establish relationships while relational databases use rows, columns, constraints and functions to achieve the same thing. A table showing the differences is shown below.

Tutorial: In Depth Review of EJB3 Entity Beans for the Component Developer Exam-a5-impedencetable.jpg
Table: Impedance differences between RDBs and OO Languages

The EJB3 Persistence API provides a means to overcome the differences between the two paradigms so that objects in the form of entities can be easily persisted into relational databases. There are seven types of relationships that are possible with entity beans. They can be broken down by directionality (i.e. unidirectional or bidirectional) as well as cardinality (i.e. one-to-one, one-to-many, many-to-one, and many-to-many). Below are outlined the different type of relationships possible:

One-to-One Unidirectional

Tutorial: In Depth Review of EJB3 Entity Beans for the Component Developer Exam-a5-onetoonebidirectional.jpg
Figure: One to One Unidirectional Relationship

A one-to-one relationships is a relationship that in a relational database is mapped using primary/foreign key associations. It establishes a parent-child relationship between the two entities of a one-to-one relationship. So for example, the User- Role relationship could be expressed with the User entity being the parent. Depending on where you have defined the foreign key, there are two ways to implement this relationship. You can use one of the following:
  • @JoinColumn annotation - when the underlying table for referencing the entity contains the foreign key to the table in which the referenced “child” entity is mapped.
  • @PrimaryKeyJoinColumn annotation - when the table has the foreign key reference to which the referenced entity is mapped.


An example of how this is coded is shown below. In unidirectional relationships, you define a property in the entity bean so that the other bean is set or retrieved. You would call the getRole() or setRole() methods to access the Role entity:

Java Code: Example of @OneToOne Annotation
/** * The user’s role */
@OneToOne 
@JoinColumn(name="ROLEID")
 // Unidirectional relationship 
private Role role;
If you are using the @PrimaryKeyJoinColumn annotations then it would be defined as below:

Java Code: Example of @OneToOne Annotation with @PrimaryKeyJoinColumn
@OneToOne(cascade={CascadeType.ALL}) 
@PrimaryKeyJoinColumn 
private Role role;
One-to-One Bidirectional Relationships

Tutorial: In Depth Review of EJB3 Entity Beans for the Component Developer Exam-a5-one-one.jpg
Figure: One-to-One Bidirectional Relationship

In bidirectional one-to-one relationships, the relational database schemas will be modeled in the same way as for unidirectional one-to-one relationships. This means that one of the tables will hold a foreign key to the other table. This is because in relational database models there is no notion of bidirectionally. In terms of the entities, there would need to be the following changes in the User - Role relationship. So the User class would have the following:@Entity

Java Code: Example of @OneToOne Bidirectional Relationship
public class Car
{
   ... 
   @OneToOne 
   // Bidirectional relationship, mappedBy 
   // is declared on the non-owning side 
   private User owner;
   ...
}
Then the Role class will have a reference back to the User:

Java Code: Example of @OneToOne Annotation Use
/** 
 The user’s car 
/
@OneToOne(mappedBy = "owner")
// Bidirectional relationship 
private Car car;
Note the use of the mappedBy() attribute. We use this attribute to setup bidirectional relationships. It also tells the persistence manager that the information for mapping the owner relationship in the database tables can be found in the class for the Car entity. A full example of how this is done is shown below:

Java Code: Example of @OneToOne Annotated Entity Use
// Create a new Car 
final Car car = new Car(); 
car.setEngine("Six-Cylinder"); 
car.setModel("Ford Taurus");
// Create a new Employee 
final User jamesBlake = new User("James Blake");
// Persist; now we have managed objects 
EntityManager em = null; 
// Assume we have this 
em.persist(jamesBlake); 
em.persist(car);
// Associate *both* sides of a bidirectional relationship 
jamesBlake.setCar(car); 
car.setOwner(jamesBlake);
One-to-Many Unidirectional Relationship

Tutorial: In Depth Review of EJB3 Entity Beans for the Component Developer Exam-a5-onetomany.jpg
Figure: One-to-Many Relationship

In one-to-many relationships, one entity bean can aggregate or hold many other entity beans. This relationship require the developer to use a collection of references to another entity when accessing the relationship field. An example of the definition of a one-to-many relationship is shown below:

Java Code: Example of @OneToMany Annotation
@Entity 
@Table(name="User") 
public class User {
	@Id 
	@Column(name="USER_ID") 
	protected Long userId; 
	... 
	@OneToMany 
	protected Set<Todo> todos; 
	...
}
Note the use of the @OneToMany annotation in the User class. It is similar in many ways with the @OnetoOne annotation. The type of collections that you can use are java.util.Collection, java.util.List, java.util.Map and java.util.Set. As with the example of a set of Todos in the User class, the collection can only contain one type of entity bean. To see how they are used see the code below:

Java Code: Example of @OneToOne Annotated Entity Use
// Create an Employee 
final User fredHurst = new User("Fred Hurst");
// Create a couple Phones 
final Todo todo1 = new Todo("Yoga Class"); 
final Todo todo2 = new Todo("Call Mom");
// Persist 
final EntityManager em = null; 
// Assume we have this 
em.persist(fredHurst); 
em.persist(todo1); 
em.persist(todo2);
Many-to-One Unidirectional Relationship

Tutorial: In Depth Review of EJB3 Entity Beans for the Component Developer Exam-a5-manytoone.jpg
Figure: Many-to-One Unidirectional Relationship

A Many-to-One unidirectional relationship is defined by when many entities reference one entity without the entity being conscious of the relationship. An example of this type of relationship is shown below:

Java Code: Example of @ManyToOne Annotation
@Entity public class User
{
   ... /**
   * The support contact for this User
   */
   @ManyToOne
   // Unidirectional 
   private Support primarySupport; 
   ...
}
In this example, the primary support class is not aware that the user has been assigned to them. The support class doesn’t define a relationship with the customer so the relationship between the User and Support entities is unidirectional.

One-to-Many and Many-to-One Bidirectional Relationships

The reason that these two relationships are grouped under one header is not only because they are intimately related but also because they are the most common relationships one will encounter in enterprise systems. So for example, in the Tudo List application, the TodoList and Todo relationship is one-to-many, since a TodoList will hold references to a collection of Todos and vice versa a Todo will hold a reference to the TodoList in which it belongs. An example of this is shown below shows the class holding the collection, the TodoList:

Java Code: Example of @OneToMany Bidirectional Annotation
@Entity
@Table(name = "TODO_LIST")
public class TodoList implements Serializable, Comparable<TodoList> {

@Id 
@Column(name="ID") 
protected Long Id; 
... 
@OneToMany(mappedBy="todoList") 
protected Set<Todo> todos; 
...
}
And here is the class being referenced, the Todo class:

Java Code: Example of @ManyToOne Annotation
@Entity
@Table(name = "TODO")
public class Todo implements Serializable, Comparable<Todo> {

@Id 
@Column(name="TODO_ID") 
protected Long bidId; 
... 
@ManyToOne 
@JoinColumn(name="TODO_LIST_ID", referencedColumnName="ID") 
protected TodoList todoList; 
...
}
As there will be multiple instances of Todos for each TodoList, the TODO table will have a foreign key reference to the primary key of the TodoList table. So the TodoList has the collection holding Todos annotated with @OneToMany with the mappedBy parameter indicating that it is mapped to the todoList variable in the Todo class. In the Todo class, we have the TodoList annotated with @ManyToOne annotation as well as the @JoinColumn specification indicating the primary/foreign key relation between the Todo and the TodoList tables. The name element in the @ManyToOne provides the foreign key, TODO_LIST_ID and the referencedColumnName provides the primary key.

Finally, remember that there is nothing preventing the @JoinColumn annotation from specifying a foreign key that refers back to a primary key in the same table. This is perfectly legal. This sort of thing is done quite often in retail where a product is classified under multiple subcategories which have one parent.

Many-to-Many Unidirectional Relationship

When you have multiple entities maintaining a collection of another entity which doesn’t maintain a reciprocal collection back to the first entities, you have a many-to-many unidirectional relationship. This along with many-to-many bidirectional relationships where the second entity does maintain a collection back to the first collection of entities are considered the most complex type of relationships to model. In a relational database, this is implemented with a join table. This allows for a bit of indirection for matching up primary keys for each table in the relationship. An example of this with the Tudo List application is shown below:

Tutorial: In Depth Review of EJB3 Entity Beans for the Component Developer Exam-a5-manytomanybidirectional.jpg
Figure: Many-to-Many Unidirectional Relationship

Although this looks very similar to the bidirectional relationship, the key difference is that we only maintain a reference in one direction. The code in the TodoList would look like the following:

Java Code: Example of @ManyToMany Unidirectional Annotation
@Entity
@Table(name = "TODO_LIST")
public class TodoList implements Serializable, Comparable<TodoList> {
   ... 
   @ManyToMany
   private Set<User> users;
   ...
 }
As this is a unidirectional relationship, there would be no code related to owning and we omit the mappedBy attribute used in the @ManyToMany annotation.

Many-to-Many Bidirectional Relationship

Tutorial: In Depth Review of EJB3 Entity Beans for the Component Developer Exam-a5-manytomany.jpg
Figure: Many-to-Many Bidirectional Relationships

As we noted before the difference with the many-to-many unidirectional relationship is that we have the reciprocal collection of references. The code for implementing this is shown below:

Java Code: Example of @ManyToMany Bidirectional Annotation
@Entity
@Table(name = "TODO_LIST")
public class TodoList implements Serializable, Comparable<TodoList> {
   ... 
   @ManyToMany(mappedBy = “todoLists”)
   private Set<User> users;
   ...
 }
And below is the code for the reciprocal collection of references held in the User class. You Which type (i.e. Set, List, Map or Collection) that you decide to use is linked closely to the referential integrity constraints that have been defined in the underlying database.

Java Code: Example of @ManyToMany Bidirectional Annotation for other Entity
@Entity
@Table(name = "USER")
public class User implements Serializable, Comparable<User> {
   ...
    @ManyToMany
   private Set<TodoList> todoLists = new HashSet<TodoList>();
   ...
}
Inheritance with EJB3 Entity Beans(Entities)

Inheritance is a concept tied to object oriented programming. There is no equivalent of inheritance used in relational databases. In order to allow for the object/relational mapping needed for this situation, there are a number of strategies that have been developed. These are:
  • Map all the related classes to a single table
  • Store each class of the inheritance hierarchy of the separated table
  • Store the superclasses and subclasses in related tables


Inheritance with a Single Table Strategy

If you use a single table strategy, all of the super and subclasses are mapped to a single table. In this situation, all of the data in the class hierarchy are stored in a single table. In order to identify the various objects, a special column is created. This is called the discriminator column and it contains the unique value for the type of object in the row. It is necessary to specify the inheritance strategy and discriminator column on the root entity. If for example, we have a superclass of type Transport, and subclasses of type Car and Motorcycle. The table would use a TransportType column as the discriminator column. So C would be the value for a car and M for a motorcycle. In this case, the code would look like the following:

Java Code: Example of Inheritance using Single Table Strategy
@Entity 
@Table(name="TRANSPORT") 
@Inheritance(strategy=InheritanceType.SINGLE_TABLE) 
@DiscriminatorColumn(name="TRANSPORT_TYPE",
discriminatorType=DiscriminatorType.STRING, length=1) 
public abstract class Transport 
...
@Entity 
@DiscriminatorValue(value="C")	
public class Car extends Transport 
...
@Entity 
@DiscriminatorValue(value="M")	
public class Motorcycle extends Transport
Note that this strategy is the default inheritance strategy used by EJB3. The disadvantage is that the strategy doesn’t really exploit the power of relational databases by relating tables specified for each object to each other.

Inheritance with Joined Tables Strategy

If you use a joined tables strategy, all of the entities are mapped to a separate table and then the tables are related by aligning the tables in a manner similar to the inheritance hierarchy. So the parent of the hierarchy would only contain the columns that are common to all the children. So in keeping with the example used in the Single Table Strategy, a column related to engine might be defined as part of the parent table as well as a discriminator column. The relationship is one-to-one with the parent and the child. An example of the code for joined tables strategy is shown below:

Java Code: Example of Inheritance using Joined Tables Strategy
@Entity 
@Table(name="TRANSPORT") 
@Inheritance(strategy=InheritanceType.JOINED) 
@DiscriminatorColumn(name="TRANSPORT_TYPE",
discriminatorType=DiscriminatorType.STRING, length=1) 
public abstract class Transport 
...
@Entity 
@Table(name=”CAR”)
@DiscriminatorValue(value="C")
@PrimaryKeyJoinColumn(name=TRANSPORT_ID”)	
public class Car extends Transport 
...
@Entity 
@Table(name=”MOTORCYCLE”)
@DiscriminatorValue(value="M")	
@PrimaryKeyJoinColumn(name=TRANSPORT_ID”)	
public class Motorcycle extends Transport
Inheritance with the Table-per-Class Strategy

This strategy is the simplest strategy for anyone including beginners to understand. Here the superclass and the subclass are stored in their own table but there is no relationship that is setup between the tables. The two key issues are that the primary keys in all of the tables must be mutually exclusive and inherited columns need to be duplicated across tables. In our case, that we be the ENGINE column. The inheritance strategy is only to be specified in the superclass. Below is an example of code implementing this strategy:

Java Code: Example of Inheritance using Table-per-Class Strategy
@Entity 
@Table(name="TRANSPORT") 
@Inheritance(strategy=InheritanceType.TABLE_PER_CLASS) 
public abstract class Transport 
...
@Entity 
@Table(name=”CAR”)
public class Car extends Transport 
...
@Entity 
@Table(name=”MOTORCYCLE”)
public class Motorcycle extends Transport
A major disadvantage of this strategy is that it provides little support for polymorphism or queries because of the separate tables. The only way to get around this is by using the SQL UNION or use separate SQL. Most experts opine that you should avoid this strategy as it makes both the implementation and maintenance more difficult.

Using persistence.xml for O/R Mapping

As with all of the EJB3 specification, it is possible to provide the same declarations in the persistence.xml and orm.xml files for entities and O/R Mapping that can be done using annotations. The recommendation that I would make is that if you want to know more about this check the schemas for the files. In general unless you are making a change for deployment reasons, it is best that you only use these files for issues specific to the deployment of your system on a particular environment (development, integration, pre production or production). Otherwise it is best to use annotations for managing the entity and O/R Mapping definitions.

OK. That’s it. We have made an in depth review of entities for those taking the component developer exam. Next up is