Accessing Databases from Web Applications

Data that is shared between web components and is persistent between
invocations of a web application is usually maintained in a database. Web
applications use the Java Persistence API (see Chapter 24, Introduction to the Java Persistence API) to access relational databases.

The Java Persistence API provides a facility for managing the object/relational
mapping (ORM) of Java objects to persistent data (stored in a database). A
Java object that maps to a database table is called an entity class. It is
a regular Java object (also known as a POJO, or plain, old Java object) with
properties that map to columns in the database table. The Duke’s Bookstore
application has one entity class, called Book that
maps to WEB_BOOKSTORE_BOOKS.

To manage the interaction of entities with the Java Persistence facility,
an application uses the EntityManager interface. This
interface provides methods that perform common database functions, such as
querying and updating the database. The BookDBAO class
of the Duke’s Bookstore application uses the entity manager to query
the database for the book data and to update the inventory of books that are
sold.

The set of entities that can be managed by an entity manager are defined
in a persistence unit. It oversees all persistence operations in the application.
The persistence unit is configured by a descriptor file called persistence.xml. This file also defines the data source, what type of transactions
the application uses, along with other information. For the Duke’s Bookstore
application, the persistence.xml file and the Book class are packaged into a separate JAR file and added to the
application’s WAR file.

As in JDBC technology, a DataSource object has
a set of properties that identify and describe the real world data source
that it represents. These properties include information such as the location
of the database server, the name of the database, the network protocol to
use to communicate with the server, and so on.

An application that uses the Java Persistence API does not need to explicitly
create a connection to the data source, as it would when using JDBC technology
exclusively. Still, the DataSource object must be created in the Application
Server.

Defining the Persistence Unit

A persistence element that identifies the
schema that the descriptor validates against and includes a persistence-unit
element.

A persistence-unit element that identifies
the name of a persistence unit and the transaction type.

An optional description element.

A jta-data-source element that specifies
the global JNDI name of the JTA data source.

The jta-data-source element indicates that the transactions
in which the entity manager takes part are JTA transactions, meaning that
transactions are managed by the container. Alternatively, you can use resource-local
transactions, which are transactions controlled by the application itself.
In general, web application developers will use JTA transactions so that they
don’t need to manually manage the life cycle of the EntityManager instance.

A resource-local entity manager cannot participate in global transactions.
In addition, the web container will not roll back pending transactions left
behind by poorly written applications.

Creating an Entity Class

As explained in Accessing Databases from Web Applications, an entity class is a component that represents a table
in the database. In the case of the Duke’s Bookstore application, there
is only one database table and therefore only one entity class: the Book class.

The Book class contains properties for accessing
each piece of data for a particular book, such as the book’s title and
author. To make it an entity class that is accessible to an entity manager,
you need to do the following:

Add the @Entity annotation to the class.

Add the @Id annotation to the property
that represents the primary key of the table.

Add the @Table annotation to the class
to identify the name of the database table if it is different from the name
of the entity class.

Obtaining Access to an Entity Manager

The BookDBAO object of the Duke’s Bookstore
application includes methods for getting the book data from the database and
updating the inventory in the database when books are sold. In order to perform
database queries, the BookDBAO object needs to obtain
an EntityManager instance.

The Java Persistence API allows developers to use annotations to identify
a resource so that the container can transparently inject it into an object.
You can give an object access to an EntityManager instance
by using the @PersistenceUnit annotation to inject
an EntityManagerFactory, from which you can obtain
an EntityManager instance.

Unfortunately for the web application developer, resource injection
using annotations can only be used with classes that are managed by a Java
EE compliant container. Because the web container does not manage JavaBeans
components, you cannot inject resources into them. One exception is a request-scoped
JavaServer Faces managed bean. These beans are managed by the container and
therefore support resource injection. This is only helpful if your application
is a JavaServer Faces application.

You can still use resource injection in a web application that is not
a JavaServer Faces application if you can do it in an object that is managed
by the container. These objects include servlets and ServletContextListener objects. These objects can then give the application’s
beans access to the resources.

In the case of Duke’s Bookstore, the ContextListener object
creates the BookDBAO object and puts it into application
scope. In the process, it passes to the BookDBAO object
the EntityManagerFactory object that was injected into ContextListener:

The JavaServer Faces version of Duke’s Bookstore gets access to
the EntityManager instance a little differently. Because
managed beans allow resource injection, you can inject the EntityManagerFactory instance into BookDBAO.

In fact, you can bypass injecting EntityManagerFactory and
instead inject the EntityManager directly into BookDBAO. This is because thread safety is not an issue with request-scoped
beans. Conversely, developers need to be concerned with thread safety when
working with servlets and listeners. Therefore, a servlet or listener needs
to inject an EntityManagerFactory instance, which is
thread-safe, whereas a persistence context is not thread-safe. The following
code shows part of the BookDBAO object included in
the JavaServer Faces version of Duke’s Bookstore:

As shown in the preceding code, an EntityManager instance
is injected into an object using the @PersistenceContext annotation.
An EntityManager instance is associated with a persistence
context, which is a set of entity instances that the entity manager is tasked
with managing.

The annotation may specify the name of the persistence unit with which
it is associated. This name must match a persistence unit defined in the application’s persistence.xml file.

The next section explains how the BookDBAO object
uses the entity manager instance to query the database.

Accessing Data from the Database

After the BookDBAO object obtains an EntityManager instance, it can access data from the database. The getBooks method of BookDBAO calls the createQuery method of the EntityManager instance to
retrieve a list of all books by bookId:

The next section describes how Duke’s Bookstore performs updates
to the data.

Updating Data in the Database

In the Duke’s Bookstore application, updates to the database involve
decrementing the inventory count of a book when the user buys copies of the
book. The BookDBAO performs this update in the buyBooks and buyBook methods:

In the buyBook method, the find method
of the EntityManager instance retrieves one of the
books that is in the shopping cart. The buyBook method
then updates the inventory on the Book object.

To ensure that the update is processed
in its entirety, the call to buyBooks is wrapped in a single
transaction. In the JSP versions of Duke’s Bookstore, the Dispatcher servlet calls buyBooks and therefore sets
the transaction demarcations.

In the following code, the UserTransaction resource
is injected into the Dispatcher servlet. UserTransaction is an interface to the underlying JTA transaction manager used
to begin a new transaction and end a transaction. After getting the UserTransaction resource, the servlet calls to the begin and commit methods of UserTransaction to mark
the boundaries of the transaction. The call to the rollback method
of UserTransaction undoes the effects of all statements
in the transaction so as to protect the integrity of the data.