Document directory
- Domain Model
- Basic knowledge of O-R framework and EJB3 JPA
- Enable Metadata Annotation
- O-R ing in standardized JPA
- Entity Manager API: a standard API for Entity Operations
- Query API
- Package
- Reference implementation
- EJB3 JPA Tool
- Conclusion
- References
Durability is critical to most enterprise applications because they need to access relational databases (such as Oracle Database 10 Gb ). If you are developing applications using Java, you may need to complete some common tasks (such as database update and retrieval), which are completed by compiling JDBC and SQL. Several object-relational (O-R) ing frameworks (such as Oracle toplink, JBoss hibernate, and Bea Kodo) have become popular in recent years because they simplify persistence issues, free Java developers from coding JDBC code so that they can concentrate on business logic. Some Java standards (such as EJB 2.x container management persistence (CMP) entity beans) also try to solve the persistence challenge, but it is not so successful.
Although there are multiple options for building the application persistence layer, there is no persistence standard available for the Java platform in both Java EE and Java SE environments. The good news is the emergence of ejb3 Java persistence API (JPA), which is part of the EJB 3.0 standard JSR-220, which standardizes the persistence API for the Java platform. JSR-220 is widely accepted by O-R ing vendors (such as toplink, Hibernate And kodo) and other leading application server vendors and JDO vendors. The ejb3 specification provides an attractive option for building a persistent layer for Enterprise Java applications.
In this article, I will introduce ejb3 Java persistence API, and I will use a simple domain object model as an example.
Domain Model
When building an enterprise application, we first design the domain object model that we want to save in the database. Then, we work with the Database Designer to determine the database mode. The domain model indicates a persistent object or entity. Entities can be people, places, or things. You store data about them. It contains data and behavior. The rich domain model has all object-oriented behavioral characteristics, such as inheritance and polymorphism.
Our simple domain model (figure 1) has a bidirectional one-to-multiple relationship between the Department and the employee entity. Fulltime and contractor objects inherit from the employee entity.
Figure 1. Sample domain object model
Basic knowledge of O-R framework and ejb3 JPA
If you have used a O-R ing framework such as Oracle toplink to build an application persistence layer, you will notice that each framework provides three tools:
- A way to execute O-R mappings in a declarative manner. This method, known as O-R ing metadata, allows you to map objects to one or more database tables. Typically, most O-R frameworks use XML to store O-R ing metadata.
- An API used to operate entities (such as performing CRUD operations. This API allows objects to be persisted, retrieved, updated, or removed. Based on the use of API and O-R ing metadata, The O-R framework represents a developer performing database operations. This API frees developers from writing JDBC or SQL code to persist domain objects.
- A query language used to retrieve objects. This is the most important aspect of durability, because illegal SQL statements may reduce the speed of the database. This method also shields the application from the proprietary SQL statements that are chaotic throughout the application. The query language allows you to retrieve entities or objects and free developers from writing SQL SELECT statements.
Ejb3 Java persistence API (JPA) provides a standard O-R ing mechanism, an entitymanager API that executes crud operations, and a way to extend the EJB-QL to retrieve entities, this standardizes the use of persistence for the Java platform. I will discuss these three aspects later.
Enable Metadata Annotation
Java SE 5.0 introduces metadata annotations. All components of Java EE (including EJB3 JPA) use metadata annotations to simplify Enterprise Java development. For more information about metadata Annotations, see Bridging the Gap: J2SE 5.0 Annotations by Kyle Downey. In EJB3 JPA, annotations can be used to define injection of objects, relationships, O-R ing, and persistent context. JPA also provides alternative options using XML descriptors. I will mainly introduce the use of metadata annotations because they greatly simplify development. However, you may prefer to use XML descriptors in the production deployment environment because they can be used to override annotations.
Standardized O-R mappings in JPA define persistent objects: Entities
An Object is a lightweight domain Object-you want to save it in Plain Old Java Object (POJO) in a relational database ). Like any POJO, an object can be an abstract or a specific class, which can expand another POJO. You can use the javax. persistence. Entity annotation to mark POJO as an object.
The following code makes the Department object in the domain model an entity:
package onjava;import java.io.Serializable;import java.util.Collection;import javax.persistence.*;@Entity@NamedQuery(name="findAllDepartment", query="select o from Department o")@Table(name="DEPT")public class Department implements Serializable { @Id @Column(nullable=false) protected Long deptNo; @Column(name="DNAME") protected String name; @Column(name="LOC") protected String location; @OneToMany(mappedBy="department") protected Collection
employees; public Department() { } ... public Collection
getEmployees() { return employees; } public void setEmployees(Collection
employees) { this.employees = employees; } public Employee addEmployee(Employee employee) { getEmployees().add(employee); employee.setDepartment(this); return employee; } public Employee removeEmployee(Employee employee) { getEmployees().remove(employee); employee.setDepartment(null); return employee; }}
Each object has a primary key. You can use the Id Annotation on the persistent field or attribute to mark it as a primary key. An object uses fields or attributes (through the setter and getter methods) to save its status. It depends on where the O-R ing annotation is used. The preceding example uses field-based access. We have used the Id Annotation with the deptNo field. To use attribute-based access, you need to use the attribute tag annotation (for example, Id), as shown below:
@Idpublic Long getDeptNo() { return deptNo; } public void setDeptNo(Long deptNo) { this.deptNo = deptNo; }
Remember to apply the same access type (field or attribute) to all objects in an object hierarchy ).
By default, each field defined in the object is inherently persistent. If you do not want to save the status of the field/attribute, you must define the field/attribute as transient, the method is to mark it with @ Transient annotation or transient modifier.
Embedded object
An embedded object is a persistent object that does not have its own identity; it is part of another object. For example, we can assume that the Address does not have its own identifier and is stored as part of the Employee entity. Therefore, Address is a candidate for embedded objects.
You can create an embedded object as follows:
@Embeddable public class Address { protected String streetAddr1; protected String streetAddr2; protected String city; protected String state; ..}
The following describes how to define an object as an embedded object in a target object:
@Entity public class Employee { @Id @GeneratedValue(strategy=GenerationType.AUTO) protected Long id; ... @Embedded protected Address address; ...}
Link
In a typical domain model, entities are associated with each other, or they are related to each other. The relationship between two entities can be one-to-one, one-to-multiple, multiple-to-one, and multiple-to-many. These links can be annotated with onetoone, onetoone, manytoone, or manytomany. In our example, the department and employee entities have a bidirectional onetoworkflow relationship.
Since we use field-based access in the object, we specify annotations on the Link field of the Department object, as shown below:
@OneToMany(mappedBy="department")protected Collection<Employee> employees ;
For bidirectional relationships, you must specify the mappedby element (as shown above) on the other side of the link by pointing to the name of the field or attribute that owns the link.
Standardized O-R ing
You can use Java metadata annotations or XML to implement O-R ing of entities. Ejb3 JPA defines a variety of annotations for O-R ing, such as table, secondarytable, column, joincolumn, and primarykeyjoincolumn. See the ejb3 JPA specification for information about all annotations.
In our example, you can use table annotations to define tables mapped to objects, as shown below:
@Table(name="DEPT")public class Department implements Serializable {
Ejb3 JPA relies heavily on the default settings. Therefore, if no table ing is defined, the persistence provider assumes that the object is mapped to a table with the same name as the object class (in our example, Department ). If an object is mapped to multiple tables, you can use secondarytable annotations.
You can use column annotations to map persistent fields or attributes to database columns, as shown below:
@Column(name="DNAME")protected String name;
Here, dname is the name of the column mapped to the persistent field name. If the column comment is not used to define the O-R ing, the persistence engine tries to save its state in the column (using the same name as the field or attribute ).
Entity inheritance
Ejb3 JPA supports multiple entity inheritance methods. It requires two types of inherited table ing policies: Single-table-per-entity and joined-subclass. It is best to avoid using an optional table-per-class hierarchy.
The Single-table-per-entity (SINGLE_TABLE) hierarchy policy allows you to map all entities in the hierarchy to a table. In our example, FullTime and Contractor extend Employee, all of which can be mapped to a table named EMP. In other words, all data related to the Employee, FullTime, and Contractor is stored in the same table.
If the Joined Subclass policy is used, the public persistent data can be stored in the table mapped to by the superclass (for example, Employee), and tables can be created for each Subclass in the hierarchy, to store persistent fields specific to sub-classes.
You must use the Inheritance annotation in the superclass to specify the Inheritance type, as shown in the following code. This example shows the object hierarchy using the single-table-per-entity hierarchy policy.
@Entity @Table(name="EMP") @Inheritance(strategy=InheritanceType.SINGLE_TABLE) @DiscriminatorColumn(name="EMPLOYEE_TYPE", discriminatorType=DiscriminatorType.STRING, length=1) public abstract class Employee implements Serializable { ... }
Each subclass must specify the authenticator value for this object type, as shown below:
@Entity @DiscriminatorValue(value="F") public class FullTime extends Employee { @Column(name="SAL") protected Double salary; @Column(name="COMM") protected Double commission; @Column(name="DESIG")protected String designation;...}
Entity Manager API: a standard API for entity Operations
Javax. persistence. EntityManager manages object lifecycles and discloses multiple methods for performing CRUD operations on objects.
The EntityManager API is called in the transaction context. It can be called outside the EJB container (for example, from a Web application) without the need for a session bean appearance.
You must obtain the EntityManager instance before performing any entity Operations. You can use the container management or Application Management Entity Manager, and use JNDI lookup or dependency injection to obtain the EntityManager instance. As its name implies, the Java EE container manages the lifecycle of the Container Management Entity Manager. It may be mainly used in Enterprise Java applications.
You can use PersistenceContext injection to obtain the Container Management Entity Manager instance, as shown below:
@PersistenceContext(unitName="onjava") private EntityManager em;
If you use the Entity Manager managed by the application, you must manage its lifecycle. You can create an application to manage the object manager instance, as shown below:
@PersistenceUnit(unitName="onjava") private EntityManagerFactory emf; private EntityManager em = emf.createEntityManager();
You can then use the EntityManager instance to perform the CRUD operation on the entity. To close the Application Management Entity Manager instance, call the em. close () method after completing the work.
As mentioned above, the Entity Manager action that involves any database changes must be performed in the transaction context.
The following table lists some key methods of the EntityManager interface for executing entity Operations.
Method |
Purpose |
Public void persist (Object entity ); |
Persistent object instance. |
Public <T> T merge (T entity ); |
Merge and separate entity instances. |
Public void remove (Object entity ); |
Remove a physical instance. |
Public <T> T find (Class <T> entityClass, Object primaryKey ); |
Retrieves an object instance from a primary key. |
Public void flush (); |
Synchronize the object status with the database. |
You can use the persist () method to persist an object instance. For example, to persist a Contractor instance, use the following code:
@PersistenceContext(unitName="onjava")private EntityManager em; ... Contractor pte = new Contractor(); pte.setName("Nistha")pte.setHourlyRate(new Double(100.0)); em.persist(pte);
If the CascadeType of this link is set to PERSIST or ALL during Object persistence, any state changes to the associated entities will also be persistent. The entity is detached after the transaction is terminated unless the extended persistent context is being used. The merge operation allows you to merge separated entity instances with persistent context. The status of the detached entity is synchronized with the database. This will help you get rid of the anti-pattern of common Data transmission objects (DTO) in EJB 2.x, because the entities as POJO can be transmitted between layers. The only requirement is that the object class must implement the java. io. Serializable interface.
Query API
Retrieving objects is an important aspect of durability. When EJB3 JPA is used, Java Persistence Query Language (JPQL) is used to represent queries. JPQL is an extension of EJBQL, which is introduced as part of the EJB 2.0 specification. However, EJB3 JPA solves all the limitations of EJBQL and adds many new features to become a powerful query language.
Jpql is improved compared with ejbql 2.x
The following are new features of JPQL in EJB3 JPA:
- Simplified query syntax
- JOIN Operation
- Group By and Having Clause
- Subquery
- Dynamic query
- Named parameter)
- Batch update and delete
In addition, if you want to benefit from database-specific query extensions, you must use native SQL for the query entity.
Dynamic query and specified Query
You can use dynamic query or specified query (named query ). Specify that the query is stored with the object and can be reused from the application.
To create a dynamic query, use the createQuery method of the Object Manager interface as follows:
Query query = em.createQuery( "select e from Employee e where e.empNo > 1"); query.setParameter(1,100); return query.getResultList();
If you want to use this query as a specified query, use the NamedQuery annotation in the object, as shown below:
@Entity @NamedQuery(name="findAllEmployee", query="select e from Employee e where e.empNo > 1") public abstract class Employee implements Serializable { }
To execute a specified Query, first create a Query instance using the createNamedQuery method on the EntityManager interface, as shown below:
query = em.createNamedQuery(" findAllEmployee");query.setParameter(1,100); return query.getResultList();
Parameter
You can use the specified parameter (named parameter) in EJBQL query to replace the positional parameter ). For example, you can rewrite the preceding query as follows:
"Select e from Employee e where e. empNo>: empNo"
If you use a specified parameter in a query, you must set this parameter as follows:
query = em.createNamedQuery("findAllEmployee");query.setParameter("empNo",100);return query.getResultList();
Package
EJB3 JPA standardizes POJO persistence. Therefore, entities are not limited to EJB modules. They can be packaged into Web modules, ejb-jar modules, library modules at the EAR level, or standard jar files. You can also use entities in Java SE. The Descriptor (persistence. xml) must be packaged in the file that contains the object, as shown below:
<persistence> <persistence-unit name="onjava"> <provider>oracle.toplink.essentials.PersistenceProvider</provider><jta-data-source>jdbc/OracleDS</jta-data-source> ...</persistence-unit> </persistence>
This descriptor identifies the data source used by the persistent provider, persistent unit, and persistent unit. As its name implies, a persistent unit is a collection of centrally managed entities. If there is a persistent unit defined in a specific module, you do not need to identify the object class in persistence. xml; it will be dynamically discovered by the persistence provider.
Reference implementation
BEA Kodo and TopLink essenof Oracle TopLink provide reference implementation of EJB3 JPA. It can be obtained from Open JPA and GlassFish Open-source projects respectively.
You can use the code in this article on the reference implementation server or any other application server that complies with EJB3 JPA.
Ejb3 JPA Tool
Development tools can indeed help build better applications, and if you use XML to implement O-R ing, the situation may not be good. Eclipse Dali O-R ing project, tools such as Oracle JDeveloper 10.1.3 and BEA Workshop studio support EJB3 JPA.
Conclusion
EJB3 Java Persistence API standardizes the Persistence API for the Java platform. It simplifies the use of transparent durability by using metadata annotations and abnormal configuration methods. Multiple application servers support EJB3 specifications (Editor's note: BEA has released WebLogic Server EJB 3.0 Tech Preview ). With the completion of the Java EE 5.0 and EJB 3.0 specifications, you will soon see that many top-notch application servers and persistent providers will implement the EJB3 Java Persistence API. You can use the reference implementation from the GlassFish project to enable EJB3 Persistence.
References
- EJB 3.0 specification
- JPA references
- Ejbs 3.0 references
- Reference implementation of EJB3 Reference in Sun's Glassfish Project
- Blog about EJB3 and Java EE
Source:Http://www.onjava.com/pub/a/onjava/2006/05/17/standardizing-with-ejb3-java-persistence-api.html
Author other articles
- Simplify EJB development with EJB3.0