Java Persistence API

JavaPersistenceAPI

Java Persistence API

Java Persistence API

     

Java Persistence API is the standard API used for the management of the persistent data and object/relational mapping. Java Persistence API is added in Java EE 5 platform. Every application server compatible with Java EE 5 supports the Java Persistent APIs.

Java Persistence API ensures the management of persistence and object/relational mapping. These are helpful while using the JPA in the development of  applications using the platform for Java EE 5. It provides O-R mapping facility to manage relational data in java application. The Java Persistence API contains the following areas:

  • Java Persistence API
  • O-R mapping metadata
  • The query language

Features of JPA: 

Java Persistence API is a lightweight framework based on POJO for object-relational mapping. Java language metadata annotations and/or XML deployment descriptor is used for the mapping between Java objects and a relational database. It allows the SQL-like query language that works for both static as well as dynamic queries. It also allows the use of the pluggable persistence API. Java Persistence APIs are mainly depends on metadata annotations. API includes:

  • Java Persistence API
  • Metadata annotations
  • Java Persistence query language

Advantages of JPA: 

Java Persistence API is build upon the best ideas from the persistence technologies like TopLink, JDO and Hibernate. Java Persistence API is compatible with Java SE environment as well as Java EE and allows developers to take advantages of the standard persistence API. 

Persistency of data is not so easy for most of the enterprise applications because for this they require access to the relational database like Oracle 10g. It is your responsibility to update and retrieve the database by writing the code using SQL and JDBC. While several object-relational (O-R) frameworks such as JBoss Hibernate and OracleTopLink make persistence challenges simpler and became popular. They let the java developer free from writing JDBC code and to concentrate only on the business logic. In EJB 2.x, container manage persistence (CMP) try to solve the persistence challenges but not successful completely.

Persistence tier of the application can be developed in several ways but Java platform does not follow any standard that can be used by both Java EE and Java SE environment. But the Java Persistence API (JPA) part of EJB 3.0 spec (JSR-220) makes the persistence API standard for the Java platform. O/R mapping vendors like Hibernate and TopLink as well as JDO vendors and other leading application server vendors are receiving the JSR-220.

Here we are describing EJB3 JPA by using the simple domain object model by an example.

Working process of an EJB application using JPA:

Domain Model: 

While developing an enterprise application, first design the domain object model required to persist the data in the database. Domain model represents the persistence objects or entities in the database. An entity represents a row in the data. An entity may be a person, place or a thing about which you want to store the data in the database. A rich domain model includes the characteristics of all the object oriented behavior like inheritance, polymorphism and many more. 

While developing an enterprise application, first design the domain object model to persist the data in the database then design the database schema with the help of database designer.

The figure illustrated below shows the bi-directional one-to-many relationship between the Employee and Department. The Contractor and the fulltime entities are inherited from the entity Employee.

   Sample domain object model

The Basics of EJB3 JPA and O-R Mapping Framework: Each of the O-R mapping framework such as Oracle TopLink provides three facilities:

  1. It defines a declarative way known as O-R mapping metadata to perform O-R mapping. Most of the framework use XML to store the O-R mapping metadata.
  2. An API is required to manipulate like to perform CRUD (CRUD stands for create, read, update, and delete) operations. The API allows you to persist, remove, update or retrieve the object from the database. O-R framework performs operations using the API and the O-R mapping metadata on your behalf. 
  3. Use of a query language for retrieving objects from the database is the proper way since improper SQL statements may result in slow down the performance of the operation performing on the database. A query language allows to retrieve the entities from the database and spares you from writing the SQL SELECT statements.

EJB 3 provides a standard way to use the persistence by providing a standard O-R mapping mechanism, a way to extend EJB-QL to retrieve entities and an EntityManager API to perform CRUD operations.

EJB3 Java Persistence API (JPA) standardizes the use of persistence for the Java platform by providing a standard mechanism for O-R mapping, an EntityManager API to perform CRUD operations, and a way to extend EJB-QL to retrieve entities. I'll discuss these three aspects of JPA later.

Metadata Annotation in Action: Metadata annotations are first time introduced in Java SE 5.0. To make the development easy all the components of Java EE including EJB3 uses the metadata annotations. In EJB3 JPA annotation defines the objects, O-R mappings, and the relationships among them. JPA also have another option to use XML descriptor, But use of the metadata annotations make the development simpler and more efficient.

Entities: 

An entity can be considered as a light weight persistence domain object. An entity defines a table in a relational database and each instance of an entity corresponds to a row in that table. An entity refers to a logical collection of data that can be stored or retrieved as a whole. For example, in a banking application, Customer and BankAccount can be treated as entities. Customer name, customer address etc can be logically grouped together for representing a Customer entity. Similarly account number, total balance etc may be logically grouped under BankAccount entity.

Persistence fields or persistent properties defines the persistent state of an entity. To map the entities and their relationship to the data in the relational database these entities use the object-relational mapping.

Requirements of Entity Classes: There are some requirements that an entity must follow:

  • The class must contain either a public or a protect no argument constructor, while it can contain other constructors.
  • The class as well as methods and persistence instance variables must not be declared as final.
  • Use the annotation javax.persistence.Entity to annotate the class.
  • Declare the persistence instance variables as protected, private or package-private so that they can directly accessed only by the entity class's methods.
  • Entity class may extend the entity as well as non-entity classes or vice-versa.
  • The class must implement the serializable interface if an entity instance is passed by value.

Persistence Fields and Properties in Entity Classes: There are two ways to access the persistent state of an entity either by instance variables or by using the JavaBeans-style properties. The fields or the properties must follow the Java language types: 

  • Java primitive types
  • java.lang.String
  • Other serialization types including:
  • wrappers of java primitive types
  • java.util.Date
  • java.util.Calender
  • java.math.BigDecimal
  • java.math.BigInteger
  • java.sql.Time
  • java.sql.Date
  • java.sql.TimeStamp
  • User-defined serializable types
  • char[]
  • Character[]
  • byte[]
  • Byte[]
  • Enumerated types
  • Other entities and/or collection of entities
  • Embedded classes

Entity uses the persistent fields while mapping annotations. Annotations are applied to the entity's instance variable. On the other hand entity uses the persistence properties while mapping annotations. Annotations are applied to the entity's getter methods for JavaBeans-style properties. We can not apply mapping annotations to both fields as well as properties simultaneously in a single entity.

Persistence Fields: Persistence accesses the entity class instance variables directly at runtime, if the entity class uses persistence fields. It is necessary to apply the object/relational mapping annotation on the instance variables.

Persistent Properties: Entity must follow the method conventions of JavaBeans components while using the persistent properties. JavaBeans-style properties use getter and setter methods that are used after the entity class's instance variable names. There is a getter and a setter method for each persistence property. In case of a boolean property you may use isProperty instead of getProperty. Lets take an example to clarify this:

Suppose an entity of type customer uses persistent property that has a private instance variable named firstName, the class defines two methods named getFirstName and setFirstName to retrieve and set the values of the instance variable. Use the following method signature for a single-valued persistent property.

  • Type getProperty()
  • void setProperty(Type type)

Multi-valued (Collection-valued) persistent fields and properties must use the supported Java collection interfaces without worrying whether the entity uses the persistence fields or properties. The collection interfaces may be used at the following places: 0

  • java.util.Collection
  • java.util.Set
  • java.util.Map
  • java.util.List

If the entity class uses persistent fields then the method signatures of the collection types must be one of these collection types. Suppose an entity of type customer includes a persistent property that uses a set of phone numbers then it should have the following methods:

Set<PhoneNumber> getPhoneNumber() {}

void setPhoneNumbers(Set<PhoneNumber>) {} 1

The O-R mapping annotations must be applied to the getter methods. Note here that mapping annotations can not be applied to the fields or properties marked transient or annotated transient.

Primary Keys in Entities: 

Each entity contains a unique identity contained in the object. E.g. A customer entity has an identity that might be identified by the customer number. A primary key allows a client to be a particular entity instance. Every unique entity must be associated with a primary key. To prove its uniqueness every entity may have either a simple or a composite primary key. 

 To denote the primary key property or field Simple primary key use javax.persistence.Id annotations. 2

Composite primary keys must be composed of either a single persistent property or field or a set of single persistent properties or fields. Composite primary keys uses javax.persistence.IdClass and javax.persistence.EmbededId.

The primary key, or the fields of the composite primary key (like property or field) must follow one of the following Java language types.

  • Java primitive types
  • Java primitive wrapper types
  • java.lang.String
  •  java.util.Date (the temporal type should be DATE)
  • java.sql.Date

Floating point types are not allowed to use in primary keys. 3

Primary Key Classes: A primary class must follow the certain rules:

  • The class must have an access modifier as public.
  • The class must include a public default constructor.
  • Primary key must contain the properties of the type public or protected if property-based access is used.
  • The class must be serialized.
  • The class must implement the equals(Other other) and hashCode() methods.
  • If the class has the mapping to multiple fields or properties of the entity class then the names and types of the primary key fields must match with those of the entity class. 

The fields order_Id and itemId are combined together to make the primary key to uniquely identify the composite key. The code for managing composite key is shown as:

public final class ListItemKey 
     implements Serializable
 	 {
		public Interger order_Id;
 		public int item_Id;
		public ListItemKey() {}
 		public ListItemKey(Integer order_Id, int item_Id){
 		this.order_Id = order_Id;
 		this.item_Id = item_Id;
 	    }
 	public boolean equals(Object otherOb){
 	if(this == otherOb){
 		return true;
 		}
 	if(!otherOb instanceof ListItemKey){
 		return false;
 		}
	 ListItemKey other = (ListItemKey) otherOb;
 		return ((order_Id==null?other.order_Id==null:order_Id.equals(other.order_Id))
		&&(item_Id == other.item_Id));
 		}
 	public int hashCode(){
 		return ((orderId==null?0:orderId.hashCode())^((int) itemId));
 		}
 	public String toString() {
	 return "" + orderId + "-" + itemId;
 		}
 }

Multiplicity in Entity Relationships: 
There are four types of multiplicities defined for entity relationships like one-to-one, one-to-many, many-to-one, and many-to-many. 4

One-to-one: When each entity instance is mapped to a single instance of another entity, then the mapping is known as one- to-one
mapping. One-to-one relationships use the javax.persistence.OneToOne annotation on the corresponding persistent field or property.

For Example: A reference variable in java contains the address of a single object so that there exists only one-to-one mapping between the object of the reference variable.

One-to-many: When an entity instance is related to many instances of other entities, then the relation is known as one-to-many. These types of relationships use the javax.persistence.OneToMany annotation on the corresponding field or property. 5

For Example: A sales order may contain the order of multiple items so there is a one-to-many relationship between the sales order and the items.

Many-to-many: When the multiple instances of an entity have the mapping to the multiple instances of the other entity then the mapping is said to many-to-many mapping. Many-to-many mapping relationships use the javax.persistence.ManyToMany annotation corresponding to the field or property.

For Example: A college student have the admission in several courses while each course may have many students. Therefore there is many-to-many relationship between the students and the courses. 6

Direction in Entity Relationships: A relationship can be either unidirectional or bi-directional. 

Unidirectional Relationship: A unidirectional relationship is a relationship in which only one of the two entities have the owing side. In unidirectional relationship only one entity can have the relationship property or field that may refer to the other.

Example: In the example given above, the List_Item contains the relationship field that refers to the other entity named as Product, while the Product doesn't have any knowledge about the List_Item that refers to it. 7

Bi-directional Relationships: A bi-directional relationship is the relationship in which both the entities have the owing side. In bi-directional relationship each entity in the relation have the relationship fields or property.

Example: Suppose the Order in the above example have the knowledge about the List_Item instance it has and also suppose that the List_Item have the knowledge about what the Order it belongs to, then the relationship between them is said to be the bi-directional relation.

Rules: There are some rules that each bi-directional relationship must follow: 8

  • You must use its owing side simply using the mappedBy element of the @OneToOne, @OneToMany, or @ManyToMany annotation of the inverse side of a bi-directional relationship. mappedBy element is used to designate the field or property in an entity.
  • In a one-to-one bi-directional relationship, owing side is the side that contains the corresponding foreign key.
  • In a many-to-one bi-directional relationships the many side is always the owing side of the relationship and must not define the mappedBy element.
  • In case of many-to-many bi-directional relationships either side may be the owing side.

Queries and Relationship Direction: 

Java Persistence query language navigates queries across relationships. The direction of the relationship can be determined by checking the navigation of a query from one entity to another.

Example: In case of the unidirectional relationship, in the above example a query can navigate from List_Item to Product, but can not navigate from Product to List_Item.  9

In case of the above Order and List_Item, a query can navigate in both the direction because both the entities have the bi-directional relationship.

Cascade Deletes and Relationships:

  Entities having the relationships are dependent on other entities in the relationship. Lets take the above example to clarify this: While deleting the order, the list item is also deleted since it is the part of the order, this is known as cascade delete relationship. Use the element cascade=REMOVE element to delete the cascade relationships specified for @OneToOne and OneToMany relationship. 0

Example: OneToMany(cascade=REMOVE, mappedBy="customer")

public Set<Order>getOrders() { return order; }

Entity Inheritance: Entities also supports the various features like inheritance, polymorphic queries, and polymorphic associations. Moreover they can also be the non-entity classes, while the non-entity classes can also extend the entity classes. These entity classes can be of the type either concrete or abstract.  1

Abstract Entities: An abstract class can be defined as entity simply by declaring the class with the @Entity. The difference between the abstract and the concrete entities is that the concrete entities can be instantiated while the abstract entities can not.

Concrete entities are queried same as the abstract entities. Suppose a query makes the target to an abstract entity then the query operates on all the concrete subclasses of the abstract entity.

@Entity
public abstract class Student{
@Roll_no
protected Integer StudentRoll_no;
............
}
@Entity
public class FullTimeStudent extends Student{
public Integer fee;
............
}
@Entity
public class PartTimeStudent extends Student{
protected Float classTime;
}

Mapped Superclasses: We can inherit the entities from their superclasses containing the persistence state and the mapping information but are not entities. The super class does not need to decorate with the @Entity annotation, and does not map as an entity by the Java Persistence provider. These superclasses are used in most of the cases when the multiple entity classes have the common state and mapping information. 2

Mapping superclasses are declared simply by specifying the class with the javax.persistence.MappedSuperclass annotation.

@MappedSuperclass 
public class Student{
@Roll_no
protected Integer StudentRoll_no;
............
}
@Entity
public class FullTimeStudent extends Student{
protected Integer fee;
..................
}
@Entity
public class PartTimeStudent extends Student{
protected Float classTime;
.............
}

We can not query the mapped superclasses and can also neither be used in Query operations nor EntityManager. But use the entity subclasses of the mapped superclasses to perform the Query operations or EntityManager. Entity relationship can not target to the mapped superclasses. Mapped superclass can be either of concrete or abstract type and also don't have any corresponding table in the underlying database. Entities inherited from the mapped superclasses define the table-mapping. For instance the above code snippet contains the underlying table FULLTIMESTUDENT and PARTTIMESTUDENT but did not have any STUDENT table.

Non-Entity Superclasses: As discussed above that the entities may have non-entity superclasses and these superclasses can either be abstract or concrete. The state of the non-empty superclasses and any state inherited from these superclasses are not persistent. Non-entity superclasses can be used either in Query operations or in EntityManager. While the non-entity superclasses ignore any mapping or relationship annotations. 3

Entity Inheritance Mapping Strategies: There is a way to configure the mapping between the underlying datastore and the inherited entities simply by decorating the parent class in the hierarchy with the javax.persistence.Inheritance annotation. Entities uses three types of mapping strategies to map the entity data to the underlying database.

  • A table for each concrete entity class.

  • A single table for each class hierarchy.

  • A "join" strategy for the specific fields or properties to a subclass are mapped to different tables rather than the fields that are common to the parent class.

You can configure the strategy simply by setting the "strategy" element of @Inheritance to one of the options defined in the javax.persistence.InheritanceType enumerated type: 

public enum InheritanceType{
SINGLE_TABLE, JOINED, TABLE_PER_CLASS
};
4

InheritanceType.SINGLE_TABLE is the default strategy value and is used in such situations where @Inheritance annotation is not specified in the parent class of the hierarchy.

Single Table per Class Hierarchy Strategy: This strategy corresponds to the default InheritanceType.SINGLE_TABLE, a single table in the database is mapped to all the classes in the hierarchy. This table includes a column containing a value to identify the subclass that belongs to the row represented by the instance. This column is known as discriminator column and can be specified by the javax.persistence.DiscriminatorColumn annotation at the root in the class hierarchy of the entity. The javax.persistence.DiscriminatorType enumerated type is used to set the type of the discriminator column in the database simply by setting the discriminatorTypeelement of @DiscriminatorColumn to one of the defined types. DiscriminatorTypeis defined as:  

 public enum DiscriminatorType{
 STRING, CHAR, INTEGER
 };
5

While @DiscriminatorColumn in not specified at the root of the entity hierarchy and the discriminator column is required then the persistence provider assumes the coulumn type as DiscriminatorTypeSTRING and column name as DTYPE by default.z