Showing posts with label JPA. Show all posts
Showing posts with label JPA. Show all posts

JPQL Overview- Getting Started

Query Basics

SELECT x FROM Magazine x

The preceding is a simple JPQL query for all Magazine entities.

public Query createQuery (String jpql);

The EntityManager.createQuery method creates a Query instance from a given JPQL string.

public List getResultList ();

Invoking Query.getResultList executes the query and returns a List containing the matching objects. The following example executes our Magazine query above:

EntityManager em = ...
Query q = em.createQuery ("SELECT x FROM Magazine x");
List<Magazine> results = q.getResultList ();

A JPQL query has an internal namespace declared in the from clause of the query. Arbitrary identifiers are assigned to entities so that they can be referenced elsewhere in the query. In the query example above, the identifier x is assigned to the entity Magazine.
[Note] Note

The as keyword can optionally be used when declaring identifiers in the from clause. SELECT x FROM Magazine x and SELECT x FROM Magazine AS x are synonymous.

Following the select clause of the query is the object or objects that the query returns. In the case of the query above, the query's result list will contain instances of the Magazine class.
[Note] Note

When selecting entities, you can optionally use the keyword object. The clauses select x and SELECT OBJECT(x) are synonymous.

The optional where clause places criteria on matching results. For example:

SELECT x FROM Magazine x WHERE x.title = 'JDJ'

Keywords in JPQL expressions are case-insensitive, but entity, identifier, and member names are not. For example, the expression above could also be expressed as:

SELECT x FROM Magazine x WHERE x.title = 'JDJ'

But it could not be expressed as:

SELECT x FROM Magazine x WHERE x.TITLE = 'JDJ'

As with the select clause, alias names in the where clause are resolved to the entity declared in the from clause. The query above could be described in English as "for all Magazine instances x, return a list of every x such that x's title field is equal to 'JDJ'".

JPQL uses SQL-like syntax for query criteria. The and and or logical operators chain multiple criteria together:

SELECT x FROM Magazine x WHERE x.title = 'JDJ' OR x.title = 'JavaPro'

The = operator tests for equality. <> tests for inequality. JPQL also supports the following arithmetic operators for numeric comparisons: >, >=, <, <=. For example:

SELECT x FROM Magazine x WHERE x.price > 3.00 AND x.price <= 5.00

This query returns all magazines whose price is greater than 3.00 and less than or equal to 5.00.

SELECT x FROM Magazine x WHERE x.price <> 3.00

This query returns all Magazines whose price is not equals to 3.00.

You can group expressions together using parentheses in order to specify how they are evaluated. This is similar to how parentheses are used in Java. For example:

SELECT x FROM Magazine x WHERE (x.price > 3.00 AND x.price <= 5.00) OR x.price = 7.00

This expression would match magazines whose price is 4.00, 5.00, or 7.00, but not 6.00. Alternately:

SELECT x FROM Magazine x WHERE x.price > 3.00 AND (x.price <= 5.00 OR x.price = 7.00)

This expression will magazines whose price is 5.00 or 7.00, but not 4.00 or 6.00.

JPQL also includes the following conditionals:

*

[NOT] BETWEEN: Shorthand for expressing that a value falls between two other values. The following two statements are synonymous:

SELECT x FROM Magazine x WHERE x.price >= 3.00 AND x.price <= 5.00

SELECT x FROM Magazine x WHERE x.price BETWEEN 3.00 AND 5.00

*

[NOT] LIKE: Performs a string comparison with wildcard support. The special character '_' in the parameter means to match any single character, and the special character '%' means to match any sequence of characters. The following statement matches title fields "JDJ" and "JavaPro", but not "IT Insider":

SELECT x FROM Magazine x WHERE x.title LIKE 'J%'

The following statement matches the title field "JDJ" but not "JavaPro":

SELECT x FROM Magazine x WHERE x.title LIKE 'J__'

*

[NOT] IN: Specifies that the member must be equal to one element of the provided list. The following two statements are synonymous:

SELECT x FROM Magazine x WHERE x.title IN ('JDJ', 'JavaPro', 'IT Insider')

SELECT x FROM Magazine x WHERE x.title = 'JDJ' OR x.title = 'JavaPro' OR x.title = 'IT Insider'

*

IS [NOT] EMPTY: Specifies that the collection field holds no elements. For example:

SELECT x FROM Magazine x WHERE x.articles is empty

This statement will return all magazines whose articles member contains no elements.
*

IS [NOT] NULL: Specifies that the field is equal to null. For example:

SELECT x FROM Magazine x WHERE x.publisher is null

This statement will return all Magazine instances whose "publisher" field is set to null.
*

NOT: Negates the contained expression. For example, the following two statements are synonymous:

SELECT x FROM Magazine x WHERE NOT(x.price = 10.0)

SELECT x FROM Magazine x WHERE x.price <> 10.0

10.1.2. Relation Traversal

Relations between objects can be traversed using Java-like syntax. For example, if the Magazine class has a field named "publisher" or type Company, that relation can be queried as follows:

SELECT x FROM Magazine x WHERE x.publisher.name = 'Random House'

This query returns all Magazine instances whose publisher field is set to a Company instance whose name is "Random House".

Single-valued relation traversal implies that the relation is not null. In SQL terms, this is known as an inner join. If you want to also include relations that are null, you can specify:

SELECT x FROM Magazine x WHERE x.publisher.name = 'Random House' or x.publisher is null

You can also traverse collection fields in queries, but you must declare each traversal in the from clause. Consider:

SELECT x FROM Magazine x, IN(x.articles) y WHERE y.authorName = 'John Doe'

This query says that for each Magazine x, traverse the articles relation and check each Article y, and pass the filter if y's authorName field is equal to "John Doe". In short, this query will return all magazines that have any articles written by John Doe.
[Note] Note

The IN() syntax can also be expressed with the keywords inner join. The statements SELECT x FROM Magazine x, IN(x.articles) y WHERE y.authorName = 'John Doe' and SELECT x FROM Magazine x inner join x.articles y WHERE y.authorName = 'John Doe' are synonymous.
10.1.3. Fetch Joins

JPQL queries may specify one or more join fetch declarations, which allow the query to specify which fields in the returned instances will be pre-fetched.

SELECT x FROM Magazine x join fetch x.articles WHERE x.title = 'JDJ'

The query above returns Magazine instances and guarantees that the articles field will already be fetched in the returned instances.

Multiple fields may be specified in separate join fetch declarations:

SELECT x FROM Magazine x join fetch x.articles join fetch x.authors WHERE x.title = 'JDJ'

[Note] Note

Specifying the join fetch declaration is functionally equivalent to adding the fields to the Query's FetchConfiguration. See Section 5.6, “Fetch Groups”.

10.1.4. JPQL Functions

As well as supporting direct field and relation comparisons, JPQL supports a pre-defined set of functions that you can apply.

*

CONCAT(string1, string2): Concatenates two string fields or literals. For example:

SELECT x FROM Magazine x WHERE CONCAT(x.title, 's') = 'JDJs'

*

SUBSTRING(string, startIndex, length): Returns the part of the string argument starting at startIndex (1-based) and ending at length characters past startIndex.

SELECT x FROM Magazine x WHERE SUBSTRING(x.title, 1, 1) = 'J'

*

TRIM([LEADING | TRAILING | BOTH] [character FROM] string: Trims the specified character from either the beginning (LEADING), the ending (TRAILING), or both (BOTH) the beginning and ending of the string argument. If no trim character is specified, the space character will be trimmed.

SELECT x FROM Magazine x WHERE TRIM(BOTH 'J' FROM x.title) = 'D'

*

LOWER(string): Returns the lower-case of the specified string argument.

SELECT x FROM Magazine x WHERE LOWER(x.title) = 'jdj'

*

UPPER(string): Returns the upper-case of the specified string argument.

SELECT x FROM Magazine x WHERE UPPER(x.title) = 'JAVAPRO'

*

LENGTH(string): Returns the number of characters in the specified string argument.

SELECT x FROM Magazine x WHERE LENGTH(x.title) = 3

*

LOCATE(searchString, candidateString [, startIndex]): Returns the first index of searchString in candidateString. Positions are 1-based. If the string is not found, returns 0.

SELECT x FROM Magazine x WHERE LOCATE('D', x.title) = 2

*

ABS(number): Returns the absolute value of the argument.

SELECT x FROM Magazine x WHERE ABS(x.price) >= 5.00

*

SQRT(number): Returns the square root of the argument.

SELECT x FROM Magazine x WHERE SQRT(x.price) >= 1.00

*

MOD(number, divisor): Returns the modulo of number and divisor.

SELECT x FROM Magazine x WHERE MOD(x.price, 10) = 0

*

CURRENT_DATE: Returns the current date.
*

CURRENT_TIME: Returns the current time.
*

CURRENT_TIMESTAMP: Returns the current timestamp.

10.1.5. Polymorphic Queries

All JPQL queries are polymorphic, which means the from clause of a query includes not only instances of the specific entity class to which it refers, but all subclasses of that class as well. The instances returned by a query include instances of the subclasses that satisfy the query conditions. For example, the following query may return instances of Magazine, as well as Tabloid and Digest instances, where Tabloid and Digest are Magazine subclasses.

SELECT x FROM Magazine x WHERE x.price < 5

10.1.6. Query Parameters

JPQL provides support for parameterized queries. Either named parameters or positional parameters may be specified in the query string. Parameters allow you to re-use query templates where only the input parameters vary. A single query can declare either named parameters or positional parameters, but is not allowed to declare both named and positional parameters.

public Query setParameter (int pos, Object value);

Specify positional parameters in your JPQL string using an integer prefixed by a question mark. You can then populate the Query object with positional parameter values via calls to the setParameter method above. The method returns the Query instance for optional method chaining.

EntityManager em = ...
Query q = em.createQuery ("SELECT x FROM Magazine x WHERE x.title = ?1 and x.price > ?2");
q.setParameter (1, "JDJ").setParameter (2, 5.0);
List<Magazine> results = q.getResultList ();

This code will substitute JDJ for the ?1 parameter and 5.0 for the ?2 parameter, then execute the query with those values.

public Query setParameter (String name, Object value);

Named parameter are denoted by prefixing an arbitrary name with a colon in your JPQL string. You can then populate the Query object with parameter values using the method above. Like the positional parameter method, this method returns the Query instance for optional method chaining.

EntityManager em = ...
Query q = em.createQuery ("SELECT x FROM Magazine x WHERE x.title = :titleParam and x.price > :priceParam");
q.setParameter ("titleParam", "JDJ").setParameter ("priceParam", 5.0);
List<Magazine> results = q.getResultList ();

This code substitutes JDJ for the :titleParam parameter and 5.0 for the :priceParam parameter, then executes the query with those values.
10.1.7. Ordering

JPQL queries may optionally contain an order by clause which specifies one or more fields to order by when returning query results. You may follow the order by field clause with the asc or desc keywords, which indicate that ordering should be ascending or descending, respectively. If the direction is omitted, ordering is ascending by default.

SELECT x FROM Magazine x order by x.title asc, x.price desc

The query above returns Magazine instances sorted by their title in ascending order. In cases where the titles of two or more magazines are the same, those instances will be sorted by price in descending order.
10.1.8. Aggregates

JPQL queries can select aggregate data as well as objects. JPQL includes the min, max, avg, and count aggregates. These functions can be used for reporting and summary queries.

The following query will return the average of all the prices of all the magazines:

EntityManager em = ...
Query q = em.createQuery ("SELECT AVG(x.price) FROM Magazine x");
Number result = (Number) q.getSingleResult ();

The following query will return the highest price of all the magazines titled "JDJ":

EntityManager em = ...
Query q = em.createQuery ("SELECT MAX(x.price) FROM Magazine x WHERE x.title = 'JDJ'");
Number result = (Number) q.getSingleResult ();

10.1.9. Named Queries

Query templates can be statically declared using the NamedQuery and NamedQueries annotations. For example:

@Entity
@NamedQueries({
@NamedQuery(name="magsOverPrice",
query="SELECT x FROM Magazine x WHERE x.price > ?1"),
@NamedQuery(name="magsByTitle",
query="SELECT x FROM Magazine x WHERE x.title = :titleParam")
})
public class Magazine
{
...
}

These declarations will define two named queries called magsOverPrice and magsByTitle.

public Query createNamedQuery (String name);

You retrieve named queries with the above EntityManager method. For example:

EntityManager em = ...
Query q = em.createNamedQuery ("magsOverPrice");
q.setParameter (1, 5.0f);
List<Magazine> results = q.getResultList ();

EntityManager em = ...
Query q = em.createNamedQuery ("magsByTitle");
q.setParameter ("titleParam", "JDJ");
List<Magazine> results = q.getResultList ();

10.1.10. Delete By Query

Queries are useful not only for finding objects, but for efficiently deleting them as well. For example, you might delete all records created before a certain date. Rather than bringing these objects into memory and delete them individually, JPA allows you to perform a single bulk delete based on JPQL criteria.

Delete by query uses the same JPQL syntax as normal queries, with one exception: begin your query string with the delete keyword instead of the select keyword. To then execute the delete, you call the following Query method:

public int executeUpdate ();

This method returns the number of objects deleted. The following example deletes all subscriptions whose expiration date has passed.

Example 10.1. Delete by Query

Query q = em.createQuery ("DELETE s FROM Subscription s WHERE s.subscriptionDate < :today");
q.setParameter ("today", new Date ());
int deleted = q.executeUpdate ();

10.1.11. Update By Query

Similar to bulk deletes, it is sometimes necessary to perform updates against a large number of queries in a single operation, without having to bring all the instances down to the client. Rather than bring these objects into memory and modifying them individually, JPA allows you to perform a single bulk update based on JPQL criteria.

Update by query uses the same JPQL syntax as normal queries, except that the query string begins with the update keyword instead of select. To execute the update, you call the following Query method:

public int executeUpdate ();

This method returns the number of objects updated. The following example updates all subscriptions whose expiration date has passed to have the "paid" field set to true.

Example 10.2. Update by Query

Query q = em.createQuery ("UPDATE Subscription s SET s.paid = :paid WHERE s.subscriptionDate < :today");
q.setParameter ("today", new Date ());
q.setParameter ("paid", true);
int updated = q.executeUpdate (); Click here to View more...

JPA 2.0 Reference Implementation

Open Source Persistence Framework Builds on Contribution from Oracle

SANTA CLARA, Calif. -- The Eclipse Foundation today announced that Sun, the lead for the Java(TM) Persistence API (JPA) 2.0, JSR 317 standard has selected the EclipseLink project as the reference implementation. The Eclipse Persistence Services Project (EclipseLink), led by Oracle, delivers an open source runtime framework supporting key persistence standards. The EclipseLink project provides a rich set of services that address complex mapping, performance and scalability and advanced functionality required for enterprise Java applications.

JSR 317, the Java Persistence API, is the Java API for the management of persistence and object/relational mapping for Java Platform, Enterprise Edition (Java EE) and Java Platform, Standard Edition environments. As the reference implementation, EclipseLink will provide a proven, commercial quality persistence solution that can be used in both Java SE and Java EE applications.

"Using EclipseLink as the reference implementation of JSR 317 is another great example of the JCP and Eclipse communities working together to streamline the development of Java software applications," said Mike Milinkovich, executive director of the Eclipse Foundation. "Open collaboration such as this helps drive the wide adoption of technology."

To provide an extensible framework that enables Java software developers to interact with relational databases, XML, and Enterprise Information Systems (EIS) in an efficient and productive manner, the EclipseLink project will deliver persistence services that focus on performance, productivity, and flexibility. The EclipseLink project was initiated with Oracle's contribution of the full source code and test suite for Oracle[R] TopLink. The project builds on the success of TopLink Essentials which is featured in Sun Microsystems' GlassFish(TM) Open Source Application Server, the JPA 1.0 reference implementation, which was also based on Oracle TopLink.

"The decision to use EclipseLink within GlassFish V3, Sun's open source reference implementation of the Java EE 6 standard, is in direct response to the requests for advanced features we have received from our user community and exemplifies the innovation and success of the open source initiatives at Sun. Seeing yet another community help advance a JCP standard demonstrates the strong adoption of Java technology and the JCP. We are enthusiastic with this opportunity to work with Oracle and the Eclipse Foundation," said Karen Tegan Padir, vice president of Infrastructure Software, Sun. "The GlassFish community continues to grow and demand enterprise-class solutions. Our association with EclipseLink is an example of multiple communities and partners working together to deliver on the Java software community's requests."

"As the EclipseLink project lead, providing the reference implementation for JPA 2.0 complements Oracle's ongoing commitment to provide flexibility and choice to the Java software and open source developer communities," said Dennis Leung, vice president of Engineering, Oracle. "Leveraging over a decade of commercial usage, the EclipseLink project provides a comprehensive open source solution focused on standards and the advanced features required by the next generation of enterprise Java software applications."

More details about the EclipseLink project and JSR 317 can be found at:

http://www.eclipse.org/eclipselink/

http://jcp.org/en/jsr/detail?id=317

About the Eclipse Foundation

Eclipse is an open source community, whose projects are focused on building an open development platform comprised of extensible frameworks, tools and runtimes for building, deploying and managing software across the lifecycle. A large, vibrant ecosystem of major technology vendors, innovative start-ups, universities and research institutions and individuals extend, complement and support the Eclipse Platform.

The Eclipse Foundation is a not-for-profit, member supported corporation that hosts the Eclipse projects. Full details of Eclipse and the Eclipse Foundation are available at www.eclipse.org.

All company/product names and service marks may be trademarks or registered trademarks of their respective companies.

Sun, the Sun logo, Sun Microsystems, Java, JCP, GlassFish and The Network Is The Computer are trademarks or registered trademarks of Sun Microsystems, Inc. in the United States and other countries.

Click here to View more...

EJB 3 and JPA Project Setup

Skeleton Project Setup


  1. Download this file: JpaAndEjb3.7z
  2. Download this file: Ejb3AndJpaPrefs.epf
  3. Use 7-zip to expand this file somewhere (for this example we'll use C:/workspaces)
  4. Start Eclipse
  5. Select the directory where you extracted this file and add to it JpaAndEjb3 (C:/workspaces/JpaAndEjb3)
  6. Pull down the File menu and select Import
  7. Under the General tab, select Prefererences and click Next
  8. Click Browse* and select the file you downloaded in the second step
  9. Click Finish
  10. Pull down the File menu and select Import
  11. Under the General tab, select Existing Projects into Workspace
  12. Click on Browse and go to the workspace directory and click OK (C:/workspaces/JpaAndEjb3 - note you should just be able to click Browse and then OK)
  13. Select all of the listed projects and click Finish**
Click here to View more...

JPA - In Depth

Introduction

Java Persistence API (JPA) provides POJO (Plain Old Java Object) standard and object relational mapping (OR mapping) for data persistence among applications. Persistence, which deals with storing and retrieving of application data, can now be programmed with Java Persistence API starting from EJB 3.0 as a result of JSR 220. This API has borrowed many of the concepts and standards from leading persistence frameworks like Toplink (from Oracle) and Hibernate (from JBoss). One of the great benefits of JPA is that it is an independent API and can nicely integrate with J2EE as well as J2SE applications.

[POJO – Plain Old Java Object is a term used to refer Java objects that do not extend or implement some specialized classes. Therefore, all normal Java objects are POJO’s only. The following classes are not POJO classes.


class MyServlet extends HttpServlet {}
class MyRemote implements SessionBean {}

In the above cases, both MyServlet and MyRemote extends and implement specialized Servlet and Bean classes, therefore, these classes cannot be termed as POJO’s.

When we say that JPA follows the POJO standard, it follows that the entities (or the entity class) are very regular and normal Java classes, in the sense that they doesn’t need to extend or implement some specialized classes].

[OR Mapping – Object-Relation mapping is the process of the transformation of the data between the class objects and databases. Applications can depend on an OR-M like tool that greatly simplifies this work instead of manually coding the transformation process.]

About Persistence Entites

Persistent Data normally refers to permanent data in an application. The state of these data is made permanent by storing them in a persistent medium like database, files or a disk tape. In JPA terms, these persistent data are referred as entities. 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.

Since entities form the heart of the JPA, they have some unique characteristics like persistability, identity and transactionability. The property of persistability deals with the storing and retrieving of entity from and to a persistent medium like database. Identity property is usually used to identity one unique entity among multiple entities (or multiple entity instances) in a database. All the CRUD operations (Create, Update and Delete) for entity objects will occur within a transactional context and it is one of the major characteristic for an entity object as the real state of an entity depends whether a transaction completes (commits/fails) or not.


Persistence API

All the classes, interfaces and annotations that make up the Java Persistence API are available in a single javax.persistence package. A brief look at the core objects and concepts within the package will be much useful before dealing with some sample code.

Entites

As mentioned previously, in JPA terms an entity refers to a persistent object which can be stored and retrieved from a persistent storage. In technical terms, this entity will correspond to a Java class.

Consider the following simple java class, named MobileEntity.


class MobileEntity{

private String model;
private String manufacturer;
private Double price;
private String imeiNo;

…..
// Getters and Setters go here.
}

The above class represents a mobile object which has its own model, manufacturer, price and an imei number. Suppose, we wish to persist this mobile java class using JPA. The first step is to qualify this java class as an entity. This is done by marking the class with @Entity annotation. Marking a class with @Entity annotation will tell to the persistence engine that objects created from this class can use the support of JPA to make them persistent. After adding the @Entity annotation to the above class the code looks like this,


@Entity
class MobileEntity{

private String model;
private String manufacturer;
private Double price;
private String imeiNo;

…..
// Getters and Setters go here.
}

[A persistence engine or a persistence provider is nothing but an implementation of the Java Persistence API. Java Persistence API is just a specification from Sun and not an implementation and vendors are free to implement their own persistent framework following the JPA specification. Thus, JPA provided a pluggable interface, where more and more implementations can easily be associated with it at run-time.]

Since an entity always has an identity associated with it, it is the job of the programmer to tell to the persistence engine, how uniquely to identity an entity object. This is simply done by marking a field (or a set of fields) with the @Id annotation. A field that is marked with @Id annotation will be treated as a primary key for the table by the persistent engine.

It is an error to ignore any one of the fields in an Entity class with @Id annotation, because the persistence engine won’t be in a position to identity unique entity objects without the help of primary keys. In our case, since no two mobile phones in the world share the same IMEI (International Mobile Equipment Identity), imeiNo is an ideal candidate to be marked with @Id annotation.


@Id
private String imeiNo;

It is an error to give null values, to a primary key field, during that case, the persistence engine may throw any kind of database exception.

The following is the default values for table and column names when the persistence engine was Oracle’s Toplink during the deployment time.

  • Alias Name - MobileEntity (the unqualified (with-out the package name) name of the class).
  • Table Name - MOBILEENTITY
  • Column Names - [MODEL, MAUNFACTURER, PRICE and IMEINO] (These correspond to the variable names).

Customizing the Entity object

In most of the cases, the defaults that are created and provided by a persistence engine are sufficient. However, certain situations may demand for customization which includes factors like name collision, companies adopting standard naming conventions, etc., like that. In such a case, the entity class can greatly be customized with a huge set of annotations available in the javax.persistence package. Let us take a look one by one.


Changing the default table name

By default the table name corresponds to the unqualified name of the class. We can change this behavior with the help of @Entity annotation itself, like this.


@Entity(name = "MOBILE_ENTITY")
public class MobileEntity{
……
}
Now, the table name becomes MOBILE_ENTITY and this should be the name that must be referred in query strings (Queries are discussed later). The value to the name property must be legal in the sense, it cannot accept any keywords that are found in the query language.

Customizing the Column behaviors

The default name of the columns, their size, whether they can accept null values or not etc., can be customized using the @Column annotation. Following is the sample code that illustrates this,


@Column(name = “MOBILE_MODEL”, nullable = true, length = 35)
private String model;

@Column(name = “MOBILE_MANUFACTURER” nullable = true, length = 100)
private String manufacturer;

@Id
@Column(name = “MOBILE_IMEI_NO”, nullable = false)
private String imeiNo;

The name property, when specified will override the default column name (which is the same as that of the field name in the Entity class). The nullable property tells that whether the column can accept null values. Length property is only applicable if the type of the column is String (or VARCHAR). There are also properties like scale and precision which is applicable only when the type of the column is NUMBER.

[Note, multiple annotations can be legally applied to elements (like class, field, method etc.). In the above example the imeiNo has two annotations attached with it, namely @Id and @Column.]

Auto-generation of Primary Keys

A primary key for an entity which is usually annotated with @Id annotation can be given a value manually or we can depend on the persistence provider for the same. For this we have to use the @GeneratedValue annotation.

Consider the following example,


@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private String imeiNo;

Since the imeiNo is going to be the primary key for the mobile object, we have decorated the field with @GeneratedValue annotation, which delegates the burden of creating values from developers to the persistence engine. Also, there are 4 different methods (or strategies) for primary key generation, which are AUTO, IDENTITY, SEQUENCE and TABLE. The simplest one is the automatic primary key generation strategy which is represented as GenerationType.AUTO.

[GenerationType is an Enumeration (new feature in Java 5.0) and the four different strategies for primary key generation, namely AUTO, IDENTITY, TABLE and SEQUENCE are defined in that enumeration.]


EntityManager

This class follows the standard Manager Design pattern for managing entities. Managing an entity or a set of entities refers to the act of bring a set of Java objects under the control of EntityManager. Unless entities don’t have any explicit association with EntityManager they are just ordinary java objects (though their corresponding classes have been marked with @Entity annotation).

This EntityManager API provides services for persisting an entity, removing an entity, querying and deleting entities.

In a J2SE application, a reference to an entity manager (EntityManager) can be obtained using the entity manager factory (EntityManagerFactory) and the Persistence class. The persistence class is a helper class (or a bootstrap) used to create EntityManagerFactory objects. With EntityManagerFactory objects, references to EntityManager objects can be obtained. The following code illustrates the same,


EntityManagerFactory entityManagerFactory = Persistence.createEntityManagerFactory(“PersistentUnitName”);
EntityManager eManager = entityManagerFactory.createEntityManager();

[An EntityManagerFactory can be configured with some set of properties with the help of Persistent Units. Notice that one of the arguments to createEntityManagerFactory() is the name of the persistent unit which is discussed in the later sections.]

In a J2EE application, the container will directly inject a reference to the EntityManager using dependency injection, so the code becomes as simple like this,


@Resource
private EntityManager entityManager;

Persistence Context

To be very precise, a persistent context manages a set of entities which in turn is managed by the EntityManager. A persistent context keeps track of the state (or the changes) that an entity object may undergo. And the EntityManager takes the support of this persistence context to commit or to undo the changes. As soon as an EntityManager object is created, it is implicitly associated with a persistence context for managing a set of entities.

Persistent Context comes in two flavors, one is the transaction-scoped persistent context and the other one is extended persistent context.

Transaction-Scoped Persistence Context: Imagine that a set of entities are managed by the persistence context. At this time, we say that the entities are bound to (or attached) to the persistent context. Changes may happen to these entities and these changes will occur within a transaction. Sometimes later when the transaction ends (commits or roll-back), the entities will unbind (detached) from the persistent context. As soon as the entities are detached from the persistence context, they are no longer being managed. Any changes that happen to these entities will not be persisted as they don’t have any association with the persistence context. Such kind of persistent context whose life-time is dependent on the life-time of the transaction (for a set of entities at that particular point of time) is termed as transaction-scoped persistent context.

All the transaction-scoped persistence context are configured by injecting @PersistentContext to EntityManager objects , like this,


@PersistenceContext(name=”PersistentUnitName”)
private EntityManager entityManager;

[Note: There is no such public interface called PersitenceContext in the Java Persistence API. The EntityManager may implicitly depend on a virtual Persistence Context class for managing the entities. So, creating a transaction-scoped persistence context is nothing but creating an EntityManager object that has been configured with @PersistenceContext annotation.]

Extended Persistence Context: Unlike transaction-scoped persistence context, where the life-time of the persistence context will end as soon the transaction is completed, a persistence context may be configured to live even after a transaction completes. In such a case, all the entities that are managed by such a persistence context will still be in a manageable state only even after the transaction ends. They won’t be detached from the context. Such long-lived persistence context that will continue to exist even after the completion of a transaction is called extended persistence context.

All the extended persistence context objects are created and managed manually by the application code only (that is by the developers).

[As soon as an EntityManager object is created, an implicit Persistence context will be associated with it and it is soon kept open and prepared for managing a set of entities, meaning that the calling EntityManager.isOpen() method will always return true. Calling the EntityManager.clear() method will clear the current persistence context associated with the EntityManager and all the entities that have their associations will now be cleared and they become detached from the EntityManager. To release all the resources referenced by the EntityManager, call the close() method, After this method call, calling any of the methods will throw IllegalStateException.]



Entities and Transactions

All entities have the property of transactionability and their CRUD operations will take place within a transactional context. Transactions can be broadly classified into two types based on who actually owns (or manages) the transaction. They are JTA and Resource-local transaction.

In the case of a J2EE Application, the default transaction type is JTA (Java Transaction API), unless explicitly specified. A method can be simply annotated with @RequiresNew (or @Requires) in which case a new transaction will always started by the container and the transaction completes as soon as the method ends.

Whereas in a J2SE application, the transaction-type defaults to Resource-local, which means that the developer (or the application code) has to explicitly start and end a transaction. It means that the user has to explicitly start a transaction with the help of EntityManager object, and then have to commit it, if everything goes normal, else have to roll-back the transaction if some error occurs.

The following code shows this,


EntityTransaction userTransaction = entityManager.getTransaction();
try{
userTransaction.begin();

// Do something here.

// If everthing goes well, make a commit here.
userTransaction.commit();
}catch(Exception exception){
// Exception has occurred, roll-back the transaction.
userTransaction.rollback();
}

Operations on Entity Objects

The following are the legal operations that can be performed on Entity objects with the help of EntityManager API. As seen previously, EntityManager are objects that manage one or more entity objects with the help of an implicit persistence context.

Persisting Entity Objects:
Entity objects are like regular java objects until they become managed and made persistent by the EntityManager. The following piece of code makes an entity to become persistent and managed.


MobileEntity mobileObject = new MobileEntity();
mobileObject.set()... // Update the state values here.
entityManager.persist(mobileObject);

The persist(entityObject) methods makes the entity persistent in the underlying database and managed within the persistence context of the EntityManager, whether the persistence context is a transaction-scoped or an extended persistence context depends upon how actually the EntityManager was configured.

[What happens when a managed entity is again forced to become managed by calling the persist() method. Or what happens when the persist() method is called couple of times on the same entity object.

Whenever the persist() method is called, the persistence engine will check for the existence of that object with the help of its unique identifier (which is represented in the form of primary key). If any duplicate object is found, then a run-time exception, EntityExistsException will be thrown.]

Querying for Entities:
Developers can either depend on the EntityManager for simple search or Query objects for providing powerful search conditions for locating and querying entity objects.

Using EntityManager object:
Following are the two different methods available in EntityManager interface for querying entity objects and there are some major differences between the two.

Using the EntityManager.find() method:
The find() method takes the class name of the Entity object and the primary key value for locating a single entity object. If the object of interest cannot be located by the EntityManager, then this method will simply return null. The following code illustrates this,


MobileEntity mobile = entityManager.find(MobileEntity.class, “ABC-123”);
If (mobile != null){ // mobile object may or may not be null.
// Process the object.
}

One good thing about the find() method is that, the returned entity object soon becomes managed automatically within the persistence context of the EntityManager.

Using the EntityManager.getReference() method:
This method, like the EntityManager.find() method, takes the name of the entity class and the primary key as their arguments. But the difference is, unlike the find() method which will return null if the entity object is not found, this method will throw an exception EntityNotFFoundException. Another difference between this method and the find() method is that, the entity that is fetched by this method may be lazily loaded. That is, the state of the state of entity (like model, manufacturer, imeiNo may be lazily loaded during the first time it is actually accessed).


MobileEntity mobile = entityManager.getReference(MobileEntity.class, “ABC-123”);
// mobile object may not contain the actual state values for model, manufacturer
// and imei number, the states may be loaded during the first access.

String model = mobile.getModel();
// The persistence engine may fetch the model value for the mobile here
// at this particular point of time.
…..

Using the Query object: Discussed later.

Deleting Entities:
To remove (delete) an entity object from the database, make a call to EntityManager.remove(entityObject) method. The entity object that is passed to the remove() must be a managed entity, else the operation will fail.

Also, making this call may or may-not remove the entity immediately from the database. The algorithm that achieves the same is implementation specific. Some implementation may only mark the entity as a removed entity after this method call, and the actual deletion of the entity object in the database may happen when a flush() operation (which is discussed later) is made.

After this method call, the entity will become detached from the persistence context and it is no longer a managed one.

Updating Entities:
The EntityManager.merge(entityObject) method will make a detached entity to get associated with the current persistence context of the EntityManager. Consider the following lines of code.


// Transaction has begin.
…..
MobileEntity mobile = entityManager.find(MobileEntity.class, “ABC-123”);
…..
// Transaction ends.

mobile.set()…… // Updating the mobile object.

entityManager.merge(mobile);

In the above piece of code, a mobile entity object is located with the EntityManager.find() method. This entity is now in a managed state. Assume that the transaction ends after some point of time and also the persistence context is a transaction-scoped persistence context. As soon as the transaction completes, the persistence context will go off, (since the persistence context is a transaction-scoped persistence context). So the entity object becomes detached from the persistence context. After this any modifications that are made to the mobile object won’t be knowledgeable to the EntityManager as the mobile object has already been detached from it.

Now, calling the merge() method, will make the mobile object becomes managed, and all the recent changes that are made to it will become visible to the current persistence context of the EntityManager.

Flushing and Refreshing:

The EntityManager.flush() will synchronize all the changes that are made to the persistent entities back to the underlying database, whereas the EntityManager.refresh() does the reverse. It will update the entity object with values taken from the database. Any new values that are set to the entity objects will be lost as a result of this method call.

For example, consider the following piece of code,


MobileEntity mobile = …..
mobile.set(); // Update the state values for the mobile object.
….
entityManager.flush();
// Calling this flush method will synchronize the database with the values
// taken from the entity object.

Now consider this code,


MobileEntity mobile = …
mobile.set(); // The state values for the mobile object is updated.
…..
entityManager.refresh();
// The refresh() method will refresh the entity object with the values taken from the database.
// All the updates that are done are lost.



The Query API

One of the disadvantage of locating the entity objects using the EntityManager.find() and EntityManager.getReference() methods is, we cannot specify any powerful search criteria for searching the entity objects. All we can provide is the primary key to request for a particular object. Another fact is the class name of entity must be known. The Query API that comes with JPA is powerful in the sense more additional criteria can be specified in the run-time during executing the query.

EntityManager serves as factory classes for getting a reference to the Query objects. The query string that we specify for locating entity objects is called Java Persistent Query Language (JPQL). The current version of the JPQL is 1.0 and it is more robust flexible and object-oriented than SQL. The persistence engine will parse the query string, transform the JPQL to the native SQL before executing it.

Types of Queries

Queries can be classified into two different types depending upon how actually the query string is defined. One is the static query (Named Query) and the other one, the Dynamic Query.

Static Query

A static query (or a named query) is one which is defined statically with the help of annotation (or XML) before the entity class. A name is usually given to the query definition so that other components in the same persistent unit can refer the query using the same. For example,


@NamedQuery(name = ” MobileEntity.findAll” query = “SELECT M FROM MOBILEENTITY”)
@Entity
class MobileEntity{
}

A named query (with a name ‘Mobile.findAll’) has been defined and this query can be referenced later in the code through its name, like this.


Query findAllQuery = entityManager.createNamedQuery(“MobileEntity.findAll”);
// Execute the query.

Note that the code is referring the query by its name (‘Mobile.findAll’) by calling the createNamedQuery() method. Also, since these named queries are statically defined, during deployment time itself, the persistent engine may parse and translate the JPQL into native SQL, cache them, thereby yielding better performance.

Multiple named queries can be logically defined with the help of @NamedQueries, like this,


@NamedQueries( {
@NamedQuery(name = “Mobile.selectAllQuery” query = “SELECT M FROM MOBILEENTITY”),

@NamedQuery(name = “Mobile.deleteAllQuery” query = “DELETE M FROM MOBILEENTITY”)
} )
[The @NamedQueries is very similar like @NamedQuery, but can accept multiple @NamedQuery objects, The definition of the @NamedQueries looks like this,

@interface NamedQuries{
NamedQuery[] value;
}
The way to specify arrayed elements with the definition of an annotation is by using {}. So was defined for the @NamedQueries( {…} ) and since the property called ‘value’ is the default property name for annotation, there is no need to explicitly mention the property name in the annotation definition. Following also works well which explicitly defines the property name ‘value’ for the annotation @NamedQueries.

@NamedQueries(value = { …. } )

Dynamic Queries

Dynamic Queries are nothing but whose query strings are provided at run-time. All calls to EntityManager.createQuery(queryString) are actually creating dynamic query objects. By defining query objects in this way, we lose the efficiency and from the performance point of view, the query execution may be slow as the persistence engine has to do all the parsing and validation stuffs, along with mapping the JPQL to the SQL at the run-time.

Following code creates a dynamic query object on the fly.


String queryString = …… // Obtained during run-time.
Query dynaQuery = entityManager.createQuery(queryString);
Static Queries will be a better choice if the scenario for which the query to be executed is well known in advance.

Query Operations

Subsequent topics cover how to work with the query API for locating the entity objects, named and the positional support for Query objects and Paging Query Results for performance.

Single Result

The following code shows how to execute a query that returns a single entity object (assuming that a table called MobileEntity with field’s model, manufacturer and imei are available in the database).


Query singleSelectQuery = entityManager.createQuery(
“SELECT M FROM MOBILEENTITY WHERE M.IMEI = ‘ABC-123’”);
MobileEntity mobileObj = singleSelectQuery.getSingleResult();

The query string that’s defined inside the createQuery() method is the Java Persistence Query Language. The Java Persistent Query Language (JPQL) resembles more like a SQL. The query statement is a simple select statement that is used to select a particular mobile object with imeiNo ‘ABC-123’. M represents a named instance row, which can be used to directly refer the fields in the corresponding table.

A call to getSingleResult() will execute the query and returns a single row that matches the search criteria in the query string. If the match wasn’t successful, then the getSingleResult() will return an EntityNotFoundException. Also, if more than one matches occur during query execution (this may not happen in our case, since imeiNo is a primary key), a run-time NonUniqueResultException will be thrown.

Multiple Results

Query.getResultList() will execute a query and may return a List object containing multiple entity instances. The following code demonstrates the same.


Query multipleSelect = entityManager.createQuery(“SELECT M FROM MOBILE”);
List mobiles =
(List)multipleSelect.getResultList();

The type-cast (List) is necessary as the getResultList() method will return a non-parameterized List object. If only one mobile object is found as a result of executing the query, then this method may simple return a list with size 1. Also note that, getResultList() method can only execute on select statements as opposed to UPDATE or DELETE statements. If any statement other than SELECT statement is passed on to the method, then an IllegalStateException will be thrown at the run-time.

Working with parameters

To reuse and to execute the query more efficiently with different set of values, one can depend on the parameter support (positional and named) offered by the JPA. These techniques resembles the one we had for the java.sql.PreparedStatement where one can prepare the statement object once and can execute the query with different set of parameter values again and again.

The positional parameter is used to bind the parameter value in terms of positional index and it is denoted by ?index within the query string. Similarly the named parameter is used to substitute the parameter value which is specified in terms of :name.

Following examples will clarify the above concepts,


String selectQuery =
“SELECT M FROM MOBILE WHERE M.MODEL = ?1 and M.MANUFACTURER = ?2”;
Query selectQuery = entityManager.createQuery(selectQuery);

selectQuery.setParameter(1, model);
selectQuery.setParameter(2, manufacturer);

The above code illustrates the positional parameter support, during query execution,?1 and ?2 will be replaced with the values specified for model and manufacturer.

For named parameter, the parameter can be given with some meaningful name prefixed with :, like the below code,


String selectQuery = “SELECT M FROM MOBILE WHERE M.MODEL = :modelName and M.MANUFACTURER = :manufacturer”;
Query selectQuery = entityManager.createQuery(selectQuery);

selectQuery.setParameter(“modelName”, model);
selectQuery.setParameter(“manufacturer”, manufacturer);

It is not that only dynamic queries can be benefited with positional and named parameters. Even for statically defined queries, the same is applicable. We can embed : or ? even in the static query definitions also,


@NamedQuery(
name =
“Mobile.findByModel” query = “SELECT M FROM MOBILEENTITY WHERE M.MODEL = :modelName
)
…

And later in code,


Query namedQuery = entityManager.createNamedQuery(“Mobile.findByModel”);
namedQuery.setParameter(“modelName”, model);

Paging Query Results

Imagine that a select query is returning larger number of record entities, it may not be advisable to show the entire set of results to the end-user as it may eat performance. The following two methods can be used in tandem to solve this kind of performance issue.

Assume that we have 1000 mobile entities in our database and we wish to show only 100 objects in an application that displays them in a nice tabular view. In the following code, before calling the getResultList(), which will return all the mobile objects in the database, the query object is well configured with setMaxResults(maxResults) method (the number of maximum entity objects that will be returned) setFirstPosition(position) method (which tells starting position of the pointer is made to point to).


int maxRecords = 10;
int startPosition = 0;
String queryString = “SELECT M FROM MOBILEENTITY”;

while(true){

Query selectQuery = entityManager.createQuery(queryString);
selectQuery.setMaxResults(maxRecords);
selectQuery.setFirstResult(startPosition);
List mobiles = entityManager.getResultList(queryString);

if (mobiles.isEmpty()){
break;
}

//Process the mobile entities.
process(mobiles);
entityManager.clear();

startPosition = startPosition + mobiles.size();
}

The above code loops through all the 100 objects in the database in a more efficient way. Also note that the EntityManager.clear() method is called every time, to clear (or to detach) the mobile objects which will make the EntityManager less burdened in terms of managing the mobile objects.

Flushing Query objects

JPA provides two modes of flushing query objects namely AUTO and COMMIT (which are defined in FlushModeType Enumeration). If the AUTO mode is set on the Query object which is the default one, then any changes made to entity objects will be reflected the very next time when a select query is made. That means that the persistence engine must make sure to update all the states of the entity objects which will affect the results of a SELECT query.

The AUTO flush mode can be set explicitly on the Query by calling setFlushMode().


queryObject.setFlushMode(FlushModeType.AUTO);

When the flush mode is set to COMMIT, then the persistence engine, may only update all the state of the entities during the database COMMIT. The dirty changes applied to entity objects and then querying for the results of the entities may be unspecified.


queryObject.setFlushMode(FlushModeType.COMMIT);
[The method setFlushMode(FlushModeType) is available in both EntityManager and Query interface. If the EntityManager has been configured with setFlushMode(FlushModeType.AUTO) and the Query object has been called with setFlushMode(FlushModeType.COMMIT), then the preference will always goes to the Query object.]


Persistent Units

Before getting into the theory of what is a persistence unit and how it has relations with EntityManagerFactory and EntityManager, let us look into a sample persistence.xml file.





oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider

jdbc/sample
com.javabeat.ejb30.persistence.entities.mobile.MobileEntity









org.hibernate.ejb.HibernatePersistence

jdbc/sample
com.javabeat.ejb30.persistence.entities.mobile.OtherEntity







[A persistence.xml file is used to manage one or more persistence units. Like web.xml for a servlet application and ejb-jar.xml for an EJB application, this persistence.xml is a must for an entity application to run.]

At a very high-level, we can infer multiple persistence units within the same persistence.xml file being uniquely identified by its name tag. Each persistence unit is configured with a provider along with its data-source and with some set of entities. So, we can say that a persistence unit provides a logical grouping for some set of entities that share some configuration.

Imagine an application is having so many entity objects and these entity objects have been nicely categorized in a way that some set of entities are sharing a common provider (Toplink, for example), acting on some data-source, whereas other set of entities are depending on a different provider (Hibernate, for example). In such a case, we can define a persistent unit with some configuration properties for some set of entities and a different persistent unit with different set of configuration properties for the remaining entities. So a persistent unit is a way to categorize some set of entities that aimed to do some common goals and common configurations to share with.

Back to the above sample code, we have two different persistent units, one being configured to point to Toplink provider with the help of tag, and the other one pointing to a hibernate provider. We also have put some vendor specific hints (or properties) through the property tag (found within the properties tag). The meaning of toplink.ddl-generation with value drop-and-create-tables essentially tells the Toplink persistence engine that during deployment time, if already there exists a table for the corresponding class MobileEntity, just drop (delete ) the table and create it before using. Similarly the property-value pair “hibernate.hbm2ddl.auto-update” tells the persistence engine, to use the existing table and not to recreate it. The tag represents the name of entity class that is to be included as part of this persistent unit.

Now, that we have a basic understanding about persistent units that how they are useful in categorizing entity objects, now its time to see how EntityManager and persistent units are related. In a regular J2SE application, instances of EntityManager class are obtained through EntityManagerFactory which is turn is obtained through the boot-strap class Persistence.

The following shows the sample code to achieve the same,


String persistentUnitName = “MyMobilePersistentUnit”;
EntityManagerFactoryfactory factory = Persistence.createEntityManagerFactory(persistentUnitName); // Line 1

EntityManager entityManager = factory.createEntityManager(); // Line 2

In line 1, an instance of EntityManagerFactory is obtained with a call to createEntityManagerFactory() with the name of the persistent unit being passed as an argument. At this stage, we know that the persistent unit by name MyMobilePersistentUnit has been configured with Toplink as its provider along with a data source object with some additional vendor specific properties. Therefore, EntityManager objects being created for this kind of configuration from the EntityManagerFactory have this configuration for their entire life-time.

In the case of a J2EE application , one can instantiate an instance of EntityManager object backed up with @PersistentUnit like this,


@PersistentUnit(unitName = “MyMobilePersistentUnit”)
private EntityManager entityManager;

Now, the EntityManager object will have the set of configuration parameters being loaded as referenced by the persistent unit name “MyMobilePersistentUnit”.


Sample Application

Following is a sample code in J2SE that creates and find Employee objects.

Code for Employee.java

package com.javabeat.ejb30.persistence.entities;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;

@Entity(name = "EMPLOYEE")

@NamedQueries({
@NamedQuery(name = "Employee.findAll", query = "SELECT EMP FROM EMPLOYEE AS EMP")
})

public class Employee implements Serializable {

@Column(name = "EMP_NAME", nullable = false, length = 100)
private String name;

@Column(name = "EMP_AGE", nullable = true)
private int age;

@Column(name = "EMP_SALARY", nullable = true)
private double salary;

@Id
@Column(name = "EMP_ID", nullable = false)
private Long id;

public Employee() {
}

public String getName(){
return name;
}

public void setName(String name){
this.name = name;
}

public int getAge(){
return age;
}

public void setAge(int age){
this.age = age;
}

public double getSalary(){
return salary;
}

public void setSalary(double salary){
this.salary = salary;
}
public Long getId() {
return this.id;
}

public void setId(Long id) {
this.id = id;
}
}

The following code test the Employee entity class by creating some sample employee objects and then finding them using the Query API. Code for EmployeeTest.java:


package employee.test;

import com.javabeat.ejb30.persistence.entities.Employee;
import java.util.Arrays;
import java.util.List;
import javax.naming.Name;
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import javax.persistence.Query;

public class EmployeeTest {

private static EntityManagerFactory entityManagerFactory =
Persistence.createEntityManagerFactory("EmployeePersistentUnit");

private EntityManager entityManager;

public EmployeeTest() {
entityManager = entityManagerFactory.createEntityManager();
}

public void createEmployees(){
try{
beginTransaction();
Employee emp1 = createEmployee("Johny", 35, 10000, 1L);
entityManager.persist(emp1);
Employee emp2 = createEmployee("David", 43, 50000, 2L);
entityManager.persist(emp2);
Employee emp3 = createEmployee("Philip", 55, 70000, 3L);
entityManager.persist(emp3);
Employee emp4 = createEmployee("James", 29, 30000, 4L);
entityManager.persist(emp4);
}catch (Exception exception){
failTransaction();
}finally{
commitTransaction();
}
}

public List findAllEmployees(){
Query query = entityManager.createNamedQuery("Employee.findAll");
List employees = query.getResultList();
return ((List)employees);
}

public Employee findByName(String empName){
String queryString =
"SELECT EMP FROM EMPLOYEE AS EMP WHERE EMP.EMP_NAME = ?1";
Query query = entityManager.createQuery(queryString);
query.setParameter(1, empName);
return (Employee)query.getSingleResult();
}

public void display(List employees){
for(Employee employee : employees){
display(employee);
}
}

private void display(Employee employee){
StringBuilder results = new StringBuilder();
results.append("Name = " + employee.getName() + ", Age = " + employee.getAge() + ", ");
results.append("Salary = " + employee.getSalary() + ", Id = " + employee.getId());
System.out.println(results.toString());
}

private void beginTransaction(){
entityManager.getTransaction().begin();
}

private void commitTransaction(){
entityManager.getTransaction().commit();
}

private void failTransaction(){
entityManager.getTransaction().rollback();
}

private Employee createEmployee(String name, int age, double salary, long primaryKey){
Employee employee = new Employee();
employee.setName(name);
employee.setAge(age);
employee.setSalary(salary);
employee.setId(primaryKey);
return employee;
}
}

For the above code to work, we have to create a persistence.xml file that contains the configurations for the EntityManager object like the database name, its URL, username/password etc inside the META-INF directory. Since it is a J2SE application we have to declare the type of transaction as Resource-Local. The following is the persistence.xml

Persistence.xml file:




oracle.toplink.essentials.ejb.cmp3.EntityManagerFactoryProvider
com.javabeat.ejb30.persistence.entities.Employee

vproperty
name="toplink.jdbc.url" value="jdbc:derby://localhost:1527/sample"/>






The above example uses the apache derby database for persisting the Employee objects as represented by the provider tag.

Summary

This article began with the discussion of Java Persistent API and its advantages and what persistent entities are. Then the terminologies that are very specific to JPA like EntityManager, PersistenceContext have been discussed. The various features about the Query interface for locating Entity objects were explored in depth. Finally, it ended with Persistent Units and its relation with EntityManager objects along with a sample J2SE application.





Click here to View more...

Introduction to JPA

The Java Persistence API, sometimes referred to as JPA, is a Java programming language framework that allows developers to manage relational data in Java Platform, Standard Edition and Java Platform, Enterprise Edition applications.

The Java Persistence API originated as part of the work of the JSR 220 Expert Group.

Persistence consists of three areas:

  • the API, defined in the javax.persistence package
  • the Java Persistence Query Language
  • object/relational metadata

Contents


  • 1 Entities
  • 2 The Java Persistence Query Language
  • 3 Relationship between Java Persistence API and Enterprise JavaBeans
  • 4 Relationship between Java Persistence API and Java Data Objects API
  • 5 Relationship between Java Persistence API and Service Data Object API
  • 6 Motivation for creating Java Persistence API
  • 7 Relationship to Hibernate (Java)
  • 8 See also
  • 9 External links

Entities

A persistence entity is a lightweight Java class that typically represents a table in a relational database. Entity instances correspond to individual rows in the table. Entities typically have relationships with other entities, and these relationships are expressed through object/relational metadata. Object/relational metadata can be specified directly in the entity class file by using annotations, or in a separate XML descriptor file distributed with the application.

The Java Persistence Query Language

The Java Persistence Query Language (JPQL) is used to make queries against entities stored in a relational database. Queries resemble SQL queries in syntax, but operate against entity objects rather than directly with database tables .

Relationship between Java Persistence API and Enterprise JavaBeans

The Java Persistence API was defined as part of the EJB 3.0 specification, which is itself part of the Java EE 5 platform. You do not need an EJB container or a Java EE application server in order to run applications that use persistence, however. Future versions of the Java Persistence API will be defined in a separate JSR and specification rather than in the EJB JSR/specification.

The Java Persistence API is a replacement persistence solution of EJB 2.0 CMP.

Relationship between Java Persistence API and Java Data Objects API

The Java Persistence API was developed in part to unify the Java Data Objects API, and the EJB 2.0 Container Managed Persistence (CMP) API. This seems to have been successful as most products supporting each of those APIs now support the Java Persistence API.

The Java Persistence API specifies only relational persistence (ORM) for Java (although there are providers that support other datastores). The Java Data Objects specification(s) provides relational persistence (ORM), as well as persistence to other types of datastore.

Relationship between Java Persistence API and Service Data Object API

The Java Persistence API is designed for relational persistence, with many of the key areas taken from object-relational mapping tools such as Hibernate and TopLink. It is generally accepted that the Java Persistence API is a significant improvement on the EJB 2.0 specification. The Service Data Objects (SDO) API (JSR 235) has a very different objective to the Java Persistence API and is considered complementary. The SDO API is designed for service-oriented architectures, multiple data formats rather than only relational data, and multiple programming languages. The Java version of the SDO API is managed via the JCP and the C++ version of the SDO API is managed via OASIS.

Motivation for creating Java Persistence API

Many enterprise Java developers have been using lightweight persistent objects provided by open-source frameworks or Data Access Objects instead of entity beans because entity beans and enterprise beans were considered too heavyweight and complicated, and they could only be used in Java EE application servers. Many of the features of the third-party persistence frameworks were incorporated into the Java Persistence API, and projects like Hibernate and Open-Source Version TopLink Essentials are now implementations of the Java Persistence API.

Click here to View more...

Java Persistence API

The major theme of version 5 of the Java Platform, Enterprise Edition (Java EE, formerly referred to as J2EE) is ease of development. Changes throughout the platform make the development of enterprise Java technology applications much easier, with far less coding. Significantly, these simplifications have not changed the platform's power: The Java EE 5 platform maintains all the functional richness of the previous version, J2EE 1.4.

Enterprise developers should notice dramatic simplification in Enterprise JavaBeans (EJB) technology. Previous articles, such as Introduction to the Java EE 5 Platform and Ease of Development in Enterprise JavaBeans Technology have described the simplifications made in EJB 3.0 technology, an integral part of the Java EE 5 platform.

A major enhancement in EJB technology is the addition of the new Java Persistence API, which simplifies the entity persistence model and adds capabilities that were not in EJB 2.1 technology. The Java Persistence API deals with the way relational data is mapped to Java objects ("persistent entities"), the way that these objects are stored in a relational database so that they can be accessed at a later time, and the continued existence of an entity's state even after the application that uses it ends. In addition to simplifying the entity persistence model, the Java Persistence API standardizes object-relational mapping.

In short, EJB 3.0 is much easier to learn and use than was EJB 2.1, the technology's previous version, and should result in faster development of applications. With the inclusion of the Java Persistence API, EJB 3.0 technology also offers developers an entity programming model that is both easier to use and yet richer.

The Java Persistence API draws on ideas from leading persistence frameworks and APIs such as Hibernate, Oracle TopLink, and Java Data Objects (JDO), and well as on the earlier EJB container-managed persistence. The Expert Group for the Enterprise JavaBeans 3.0 Specification (JSR 220) has representation from experts in all of these areas as well as from other individuals of note in the persistence community.

This article supplements the earlier articles by focusing on entity-related code. Here you'll be able to examine EJB 2.1 entity beans in an application and compare them to EJB 3.0 entities in an equivalent application. More specifically, you'll be able to view side by side the source code for EJB 2.1 entity beans that use container-managed persistence and relationships and compare them to the source code for equivalently functioning EJB 3.0 entities written to the Java Persistence API. Note that in the Java Persistence API, what used to be called entity beans are now simply called entities. You'll see how much easier and streamlined the EJB 3.0 technology code is.

The article highlights some of the important features that simplify the EJB 3.0 version of the code. Although this article focuses on the Java Persistence API and its use in an EJB 3.0 container, the API can also be used outside the container -- for instance, in applications for the Java Platform, Standard Edition (Java SE, formerly referred to as J2SE). The API also provides support for pluggable, third-party persistence providers. For example, a persistence implementation from one vendor can be used with an EJB container from another vendor, provided that the container and the persistence implementation both conform to JSR 220.

This article assumes that you're familiar with the basic concepts of EJB technology that underlie EJB 2.1. If you're not, see the chapter "Enterprise Beans" in the J2EE 1.4 Tutorial. For more information about EJB 3.0 and Java Persistence concepts, see the chapter "Enterprise Beans" in the Java EE 5 Tutorial.


Contents

- The Application
- The Entities
- The Class Definition
- Persistent Fields and Properties
- Entity Identity
- Relationships
- Inheritance and Polymorphism
- Operations on Entities
- Transactions
- Queries
- Testing Entities Outside of the EJB Container
- Summary
- For More Information

First, let's look at the application in use.

The Application

This article uses the EJB 2.1 technology version of the application, the CMP Customer Sample Application, from the J2EE 1.4 samples bundle. You can download the samples bundle from the J2EE 1.4 Downloads page. The samples bundle includes instructions for installing and running the EJB 2.1 version of the application.

The EJB 3.0 version of the same application is called the Java Persistence Demo and is available for download here. The download bundle includes instructions for installing and running the EJB 3.0 version of the application.

Both versions of the application do the same thing: They interact with a relational database to store and display information about customer subscriptions to periodicals. The database stores information such as a customer's name and address, as well as the type of periodical to which the customer is subscribed -- that is, magazine, journal, or newspaper. You can submit requests to the application to display subscription-related information. For example, you can get a list of all subscriptions for a particular customer.

Figure 1 shows what some of the interactions look like. Click to enlarge each image.

Java Persistence Demo: Search for a customer Java Persistence Demo: Search for a subscription by titleJava Persistence Demo: Financial TimesJava Persistence Demo: Create a new customer Figure 1: Java Persistence Demo Interactions
Figure 1: Java Persistence Demo Interactions

The Entities

Let's examine the entity-related code within the application. First, let's look at what classes and interfaces are required for the entities in the application. Look at Figure 2. Compare the list in the EJB 2.1 version with that of the EJB 3.0 version.

Figure 2: Required Classes and Interfaces
Figure 2: Required Classes and Interfaces
Click here for a larger image

You need to code fewer classes and interfaces

For an EJB 3.0 entity, you no longer need to code interfaces such as LocalAddressHome and LocalAddress -- or even a deployment descriptor. All you need to provide is an entity class. So in the application's EJB 3.0 version, what's required for an entity has been reduced from three classes -- for local interfaces and a business class -- to one entity class. This simplification is not limited to entities. EJB 3.0 technology has eliminated the requirement for a home interface in enterprise beans of any type. In addition, you no longer need to implement the EJBObject and EJBLocalObject interfaces. For example, a session bean now requires only a bean class and a business interface, which is a simple Java technology interface.

The Class Definition

Let's now look at the code for the entities. Let's start by comparing some of the key parts of the code for the EJB 2.1 AddressBean class and the EJB 3.0 Address class. First, we'll look at the class definition. You can view the entire entity bean class and entity class by clicking on their names in the Figure 3.

Figure 3: Comparing Class Definitions
Figure 3: Comparing Class Definitions
Click here for a larger image

An entity is a Plain Old Java Object (POJO), so no boilerplate is required

The EJB 2.1 version of the entity bean class implements the javax.ejb.EntityBean interface. In fact, an EJB 2.1 entity bean class must implement this interface to interact with the EJB 2.1 container. Because of that, the bean class must also implement all of the methods in the interface: ejbRemove, ejbActivate, ejbPassivate, ejbLoad, ejbStore, setEntityContext, and unsetEntityContext. The class must implement these callback methods even if it doesn't use them, as is the case for most of these methods in the EJB 2.1 example in Figure 3.

By comparison, an EJB 3.0 entity class is a simple, nonabstract, concrete class -- a POJO, a class that you can instantiate like any other simple Java technology class, with a new operation. It does not implement javax.ejb.EntityBean or any other container-imposed interface. Because the entity class no longer implements javax.ejb.EntityBean, you are no longer required to implement any callback methods. However, you can still implement callback methods in the entity class if you need them to handle life-cycle events for the entity. Also notice the no-argument public constructor. In EJB 3.0 technology, an entity class must have a no-argument public or protected constructor.

Annotations minimize what needs to be specified

The @Entity metadata annotation marks the EJB 3.0 class as an entity. EJB 3.0 and the Java Persistence API rely heavily on metadata annotation, a feature that was introduced in J2SE 5.0. An annotation consists of the @ sign preceding an annotation type, sometimes followed by a parenthetical list of element-value pairs. The EJB 3.0 specification defines a variety of annotation types. Some examples are those that specify a bean's type, such as@Stateless; those that specify whether a bean is remotely or locally accessible, such as @Remote and @Local; transaction attributes, such as @TransactionAttribute; and security and method permissions, such as @MethodPermissions, @Unchecked, and @SecurityRoles. The Java Persistence API adds annotations, such as @Entity, that are specific to entities. The reliance on annotations in EJB 3.0 and the Java Persistence API demonstrates a significant design shift.

Defaults make things even easier

In many cases, the application can use defaults instead of explicit metadata annotation elements. In these cases, you don't have to completely specify a metadata annotation. You can obtain the same result as if you had fully specified the annotation. For example, the @Entity annotation has a name element that is used to specify the name to be used in queries that reference the entity. The name element defaults to the unqualified name of the entity class. So in the code for the Address entity, an annotation of @Entity is enough. There's no need to specify a name in the annotation. These defaults can make annotating entities very simple. In many cases, defaults are assumed when an annotation is not specified. In those cases, the defaults represent the most common specifications. For example, container-managed transaction demarcation -- in which the container, as opposed to the bean, manages the commitment or rollback of a unit of work to a database -- is assumed for an enterprise bean if no annotation is specified. These defaults illustrate the coding-by-exception approach that guides EJB 3.0 technology. The process is simpler for the developer. You need to code only when the default is inadequate.

Let's now compare how persistence is declared for fields and properties.

Figure 4: Comparing Persistent Field and Property Declarations
Figure 4: Comparing Persistent Field and Property Declarations
Click here for a larger image

Persistence declarations are simpler

In EJB 2.1 technology, you specify which fields of the class need to be persisted in a database by defining public abstract getter and setter methods for those fields and by making specifications in a deployment descriptor -- an approach that many programmers find clumsy and far from intuitive. EJB 3.0 technology does not require these specifications. In essence, persistence is built into an entity. The persistent state of an entity is represented either by its persistent fields or persistent properties.

Recall that an entity is a POJO. Like a POJO, it can have nonabstract, private instance variables, such as the AddressID variable in the Address class. In the Java Persistence API, an entity can have field-based or property-based access. In field-based access, the persistence provider accesses the state of the entity directly through its instance variables. In property-based access, the persistence provider uses JavaBeans-style get/set accessor methods to access the entity's persistent properties. All fields and properties in the entity are persisted. You can, however, override a field or property's default persistence by marking it with the @Transient annotation or the Java keyword transient.

No XML descriptor needed to declare persistent fields

EJB 2.1 technology, entity bean fields are identified as persistent fields in the bean's deployment descriptor, ejb-jar.xml, an often large and complex XML file. In addition to coding public accessor methods in the entity bean class, you must specify in the deployment descriptor a cmp-field element for each persistent field. In the Java Persistence API, you no longer need to provide a deployment descriptor, called an XML descriptor in the Java Persistence API, to specify an entity's persistent fields.

Default mappings are used where possible

In EJB 2.1 technology, you define the mapping between an entity bean's fields and their corresponding database columns in a vendor-specific deployment descriptor, such as sun-ejb-jar.xml. By contrast, the Java Persistence API does not require XML descriptors. Instead, you specify the mappings in the entity class by marking the appropriate persistent field or property accessor method with the @Column annotation. You can, however, take advantage of annotation defaults. If you don't specify an @Column annotation for a specific persistent field or property, a default mapping to a database column of the same name as the field or property name is assumed. Although you don't need to specify XML descriptors, you have the option of using them as an alternative to annotations or to supplement annotations. Using an XML descriptor might be useful in externalizing object-relational mapping information. Also, multiple XML descriptors can be useful in tailoring object-relational mapping information to different databases.

The Java Persistence API standardizes object-relational mapping, enabling fully portable applications.

Entity Identity

There are also simplifications in the way primary and composite keys for entities are specified.

Figure 5: Comparing Settings for Primary Keys
Figure 5: Comparing Settings for Primary Keys
Click here for a larger image

No XML descriptor needed to specify the primary key

In EJB 2.1 technology, the primary key for an entity bean -- that is, its unique identifier -- is specified not in the entity bean class but rather in its deployment descriptor. In the Java Persistence API, you don't need to provide an XML descriptor to specify an entity's primary key. Instead, you specify the primary key in the entity class by marking an appropriate persistent field or persistent property with the @Id annotation. You can specify composite keys in two different ways, using an @IdClass annotation or an @EmbeddedId annotation.

Relationships

So far, the focus has been on the coding simplifications that relate to basic persistence, that is, the persistence of entities and their fields or properties. Now, let's look at the coding simplifications that relate to entity relationships. To do that, let's focus on the CustomerBean class and compare it to the CustomerBean entity. The CustomerBean class has a one-to-many unidirectional relationship with AddressBean and a many-many bidirectional relationship with SubscriptionBean. Let's see how much easier it is to specify an equivalent set of relationships between the EJB 3.0 entities.

Figure 6: Comparing Relationship Declarations
Figure 6: Comparing Relationship Declarations
Click here for a larger image

Relationship declarations are simpler

Specifying container-managed relationships in EJB 2.1 technology can be quite complex. If entity bean A has a relationship with entity bean B, you must specify abstract getter and setter methods in entity bean A for the related entity bean B. In addition, you must provide a rather lengthy entry for the relationship in the ejb-jar.xml deployment descriptor. In the Java Persistence API, you specify the relationship as you would for any POJO -- through a reference to the related entity object. In addition, you specify annotations that describe the semantics of the relationship and any database table-related metadata. You do not need an XML descriptor to specify entity relationships.

Note, however, that unlike in EJB 2.1 with container-managed persistence, the application that uses the Java Persistence API is responsible for managing relationships. For example, unlike EJB 2.1 technology, the Java Persistence API requires the backpointer reference in a bidirectional relationship to be set. Assume entity A has a bidirectional relationship to entity B. In EJB 2.1 technology, all you need to do is set the relationship from A to B -- the underlying persistence implementation is responsible for setting the backpointer reference from B to A. The Java Persistence API requires the references to be set on both sides of the relationship. This means that you have to explicitly call b.setA(a) and a.setB(b).

Annotations specify multiplicity and related information

You declare the relationships in annotations that reference the related entities. Annotations on the persistent fields and properties specify the multiplicity of a relationship, such as one-to-many or many-to-many, and other information, such as cascade and eager fetching. (By comparison, in EJB 2.1 technology, this information is specified in vendor-specific settings.) For example, the @OneToMany annotation on the getAddresses accessor method in the Customer entity, specifies a one-to-many relationship with the Address entity.

The Customer entity is the owning side of the relationship. There is no associated annotation in the inverse side of the relationship. So this is a one-to-many unidirectional relationship with the Address entity. The value specified for the cascade element in the annotation specifies that life-cycle operations on the Customer entity must be cascaded to the Address entity, the target of the relationship. In other words, when a Customer instance is made persistent, any Address instances related to the Customer are also made persistent. It also means that if a Customer instance is deleted, the related Address instances are also deleted. The FetchType value specifies eager fetching -- this tells the container to prefetch the associated entities.

The owning side specifies the mapping

Notice that the many-to-many relationship between the Customer and Subscription entity classes is specified using a @ManyToMany annotation in both classes and a @JoinTable annotation in the Customer class. Either Customer or Subscription could have been specified as the owning class. In this example, Customer is the owning class, and so the @JoinTable annotation is specified in the that class. The @ManyToMany annotation in the Subscription class refers to the Customer class for mapping information through a mappedBy element. Because this example uses a join table for the relationship, the @JoinTable annotation specifies the foreign key columns of the join tables that map to the primary key columns of the related entities.

Default mappings are used for relationships where possible

You can take advantage of default mappings to simplify the coding for relationship mapping even further. If you look at the create.sql file under the setup/sql directory for the Java Persistence Demo, you will see a join table named CUSTOMER_ADDRESS. Notice that no annotations are needed in the Customer entity to specify the mapping of the Customer and Address entities to the columns in the CUSTOMER_ADDRESS table. That's because the table name and join column names are the defaults.

Inheritance and Polymorphism

An important capability of the Java Persistence API is its support for inheritance and polymorphism, something that was not available in EJB 2.1. You can map a hierarchy of entities, where one entity subclasses another, to a relational database structure, and submit queries against the base class. The queries are treated polymorphically against the entire hierarchy.

The code in the EJB 3.0 column below shows an example of the support for inheritance and polymorphism. This sample is not taken from the application code because the Java Persistence Demo does not use this feature. Here, ValuedCustomer is an entity that extends the Customer entity. The hierarchy is mapped to the CUST table:

Figure 7: Support for Inheritance and Polymorphism
Figure 7: Support for Inheritance and Polymorphism
Click here for a larger image

Annotations specify inheritance

The @Inheritance annotation identifies a mapping strategy for an entity class hierarchy. In this example, the strategy specified by the value of the strategy element is SINGLE_TABLE. This means that the base class Customer and its subclass ValuedCustomer are mapped to a single table. By the way, you can also specify a strategy that joins the base class and its subclasses or that maps them to separate tables. A single table strategy requires a discriminator column in the table to distinguish between rows in the table for the base class and rows for the subclasses. The @DiscriminatorColumn annotation identifies the discriminator column, in this case, DISC. The discriminatorType element specifies that the discriminator column contains strings. The @DiscriminatorValue annotation is used to specify the value of the discriminator column for the associated entity. Here, ValuedCustomer instances are distinguished from other Customer instances by having a value of VCUSTOMER in the discriminator column.

Defaults can be used for various inheritance specifications

As is the case in many other parts of EJB 3.0 technology and the Java Persistence API, you can rely on defaults to further simplify coding. For example, SINGLE_TABLE is the default inheritance strategy, so the code sample does not need to specify it. In fact, you don't need to specify the @Inheritance annotation if you're using single-table inheritance. The default for the discriminatorType element in the @DiscriminatorColumn annotation is STRING, so the specification in the code sample is not necessary there either. Also, for string discriminator columns, you don't need to specify a discriminator value. The default is the entity name.

Entities can inherit from other entities and from non-entities

The EJB 3.0 example illustrates inheritance from an entity. However inheritance from POJOs that are not entities -- for behavior and mapping attributes -- is also allowed. The base entity or nonentity can either be abstract or concrete.

Operations on Entities

Another pronounced simplification in the Java Persistence API is the way entity operations are performed. For example, look at the way a subscription is removed in the editCustomer.jsp file and the EJB 2.1 CustomerBean compared to the way this is done in the business interface for the EJB 3.0 session bean, CustomerSession.

Figure 8: Comparing Operations on Entities
Figure 8: Comparing Operations on Entities
Click here for a larger image

Entity operations are performed directly on the entity

In EJB 2.1 technology, a client must use the Java Naming and Directory Interface (JNDI) to lookup the bean. In doing this, JNDI acquires an object that represents the bean's home interface. In response, the EJB container creates an instance of the bean and initializes its state. The client can then call methods on the JNDI-acquired object to perform operations on the bean. In the EJB 2.1 technology code sample above, JNDI is used to acquire an object that represents the LocalSubscriptionHome interface. In the removeSubscription() business method of the CustomerBean, the findByPrimaryKey() method finds the pertinent SubscriptionBean instance and removes the reference to it. This relationship update is synchronized to the database when the transaction in which this CustomerBean's business method takes part commits. Many developers view this process as needlessly indirect and complex.

By comparison, the Java Persistence API requires no JNDI-based lookup. An EntityManager instance is used to find the pertinent Customer and Subscription entities. The reference to the Subscription instance is then removed from the Customer's subscription list. Also, the reference to the Customer instance is removed from the Subscription's customer list -- just as with POJOs.

An entity manager manages the entities

An EntityManager instance is used to manage the state and life cycle of entities within a persistence context. The entity manager is responsible for creating and removing persistent entity instances and finding entities by the entity's primary key. It also allows queries to be run on entities.

Dependencies can be injected

As illustrated in the EJB 3.0 technology code example in Figure 8, JNDI is no longer required to get references to resources and other objects in an enterprise bean's context. Instead, you can use resource and environment reference annotations in the bean class. These annotations inject a resource on which the enterprise bean has a dependency. In the EJB 3.0 technology code sample, the @PersistenceContext annotation injects an EntityManager with a transactional persistence context, on which the session bean has a dependency. The container then takes care of obtaining the reference to the needed resource and providing it to the bean. Dependency injection can dramatically simplify what you have to code to obtain resource and environmental references.

Transaction-related specifications are also simplified.

Figure 9: Comparing Transaction-Related Specifications
Figure 9: Comparing Transaction-Related Specifications
Click here for a larger image

No XML descriptor needed to specify transaction attributes

In EJB 2.1 technology, you specify the transaction attributes for container-managed transactions in an often lengthy and complex deployment descriptor. In EJB 3.0 technology, an XML descriptor is not needed to specify transaction attributes. Instead, you can use the @TransactionManagement annotation to specify container-managed transactions, as well as to specify bean-managed transactions, and the @TransactionAttribute annotation to specify transaction attributes. In the EJB 3.0 technology code sample, the @TransactionManagement annotation specifies container-managed transactions for the session bean. Because container-managed transactions are the default type of transaction demarcation, the annotation is not necessary here. The @TransactionAttribute annotation on the remove() method specifies a transaction attribute of REQUIRED, which is the default transaction type. So this annotation is not necessary either. You would need the annotation, however, to specify another transaction type, such as "Mandatory" or "Supports".

Container-managed entity managers are Java Transaction API entity managers

In the Java Persistence API, transactions involving EntityManager operations can be controlled in two ways, either through JTA or by the application through the EntityTransaction API. An entity manager whose transactions are controlled through JTA is called a JTA entity manager. An entity manager whose transactions are controlled by the EntityTransaction API is called a resource-local entity manager. A container-managed entity manager must be a JTA entity manager. JTA entity manager transactions are started and ended outside of the entity manager, and the entity manager methods share the transaction context of the session bean methods that invoke them.

Support for queries has been significantly enhanced in the Java Persistence API. Some of these enhancements are shown in Figure 10.

Figure 10: Comparing Query Specifications
Figure 10: Comparing Query Specifications
Click here for a larger image

No XML descriptor needed to specify queries

In EJB 2.1 technology, you define a query for an entity bean using Enterprise JavaBeans query language (EJB QL). You specify the query in the deployment descriptor for the bean, and associate it there with a finder or select method for the bean. In the Java Persistence API, you can define a named -- or static -- query in the bean class itself. You also have the option of creating dynamic queries. To create a named query, you first define the named query using the @NamedQuery annotation. Then you create the previously-defined query using the createNamedQuery method of the EntityManager. In the EJB 3.0 technology example, two named queries are defined in the Customer entity class: findCustomerByFirstName and findCustomerByLastName. The named queries are created in the session bean, CustomerSession, which provides the client code for the entity. To create a dynamic query, you use the createQuery method of the EntityManager. The Java Persistence API provides a Java Persistence query language that extends EJB QL. You can use Java Persistence query language or native SQL in named or dynamic queries.

Support for dynamic queries and named queries is added

The Java Persistence API provides a Query API to create dynamic queries and named queries. For example, the CustomerSession class uses the Query API on the entity manager to create the named queries findCustomerByFirstName and findCustomerByLastName. The Query method setParameter binds an argument to a named parameter. (By the way, support for named parameters is also a new feature in the Java Persistence API: both named queries and dynamic queries can use named parameters as well as positional parameters, although a single query cannot mix both types of parameters.) For example, the setParameter method in findCustomerByFirstName binds the firstname argument to the named parameter :firstName in the named query definition. The getResultList method returns the query results.

All queries that use the Java Persistence API are polymorphic

This means that when a class is queried, all subclasses that meet the query criteria are also returned.

The Java Persistence Query Language is an enhanced query language

EJB QL has been a very popular facet of EJB technology. However, despite its popularity, EJB QL has lacked some of the features of a full structured query language, such as bulk update and delete operations, outer join operations, projection, and subqueries. The Java Persistence query language adds those features. It also adds support for outer join-based prefetching. The full range of the Java Persistence query language can be used in static or dynamic queries. However the Java Persistence Demo does not use the Java Persistence query language enhancements.

Testing Entities Outside of the Container

Although this can't be demonstrated in a side-by side code comparison, testing entities outside an EJB container is now much easier. Previously, the entity bean component model -- with its requirements for home and component interfaces, abstract entity bean classes, and virtual persistent fields -- made it difficult to test entity beans outside of the container. The Java Persistence API removes the requirement for these interfaces. The only thing required for an entity bean is a concrete entity bean class -- a POJO -- that has persistent fields or persistent properties. In addition, an entity's life cycle is controlled through the entity manager, not through a home interface whose life-cycle methods are implemented by the EJB container. Because all of this makes entities less dependent on intervention by the EJB container, the entities can be more easily tested outside of the container.

Summary

The aim of the new Java Persistence API is to simplify the development of persistent entities. It meets this objective through a simple POJO-based persistence model, which reduces the number of required classes and interfaces. You model your data using POJOs, and then annotate them to tell the container about an entity's characteristics and the resources it needs. You also use annotations for object-relational mappings and entity relationships, as well as deploy-time instructions. This annotation-based approach removes the need for often long and complex, XML-based descriptors. In many cases, the annotations' defaults are enough. You code specific attributes of the annotations only when the defaults are inadequate.

Beyond these simplifications, the Java Persistence API adds capabilities that were not in EJB 2.1 technology, giving you additional power and flexibility in developing and using persistent entities. You can take advantage of query language enhancements and new features such as inheritance and polymorphism to perform more powerful and encompassing queries. You can exercise more control over queries, and perform query optimizations specific to your needs. In short, using the Java Persistence API is much simpler and more intuitive than it's predecessors, yet it offers a more robust API for creating, managing, and using persistent entities.

Click here to View more...