Professional Documents
Culture Documents
created or destroyed, request or session attributes are added, removed, or modified, and so on and so forth. The Servlet API provides a number of listener interfaces we can implement in order to react to these events. All of these interfaces are in the javax.servlet package. The following table summarizes them: LISTENER INTERFACE
ServletContextListener ServletContextAttributeListener
DESCRIPTION
Contains methods for handling context initialization and destruction events. Contains methods for reacting to any attributes added, removed, or replaced in the servlet context (application scope). Contains methods for handling request initialization and destruction events. Contains methods for reacting to any attributes added, removed, or replaced in the request. Contains methods for handling HTTP session initialization and destruction events Contains methods for reacting to any attributes added, removed, or replaced in the HTTP session.
Summary
This chapter covered how to develop, configure, package, and deploy servlets. We also covered how to process HTML form information by accessing the HTTP request object. Additionally, forwarding HTTP requests from one servlet to another was covered, as well as redirecting the HTTP response to a different server. We also discussed how to persist objects in memory across requests by attaching them to the servlet context and the HTTP session. Finally, we covered all the major new features of Servlet 3.0, including configuring web applications via annotations, pluggability through web-fragment.xml, programmatic servlet configuration, and asynchronous processing.
Database Connectivity
Any non-trivial Java EE application will persist data to a relational database. In this chapter, we will cover how to connect to a database and perform CRUD operations (Create, Read, Update, and Delete). There are two Java EE APIs that can be used to interact with a relational
database: the Java Database Connectivity (JDBC) API and the Java Persistence API (JPA). Both these APIs will be discussed in this chapter. Some of the topics covered in this chapter include: Retrieving data from a database through JDBC Inserting data into a database through JDBC Updating data in a database through JDBC Deleting data in a database through JDBC Retrieving data from a database through JPA Inserting data into a database through JPA Updating The Java Database Connectivity (JDBC) API is the standard API used for Java applications to interact with a database. Although JDBC is not part of the Java EE specification, it is used very frequently in Java EE applications. data in a database through JPA Deleting data in a database through JPA Building queries programmatically through the JPA 2.0 Criteria API Automating data validation through JPA 2.0's Bean Validation support
JDBC
JDBC allows us to send queries to a database to perform select, insert, update, and delete operations. The most common way of interacting with a database through JDBC is through the java.sql.PreparedStatement interface. Using prepared statements through this interface offers a number of benefits over using standard JDBC statement objects. Some of the benefits of prepared statements include: Prepared statements are compiled into the RDBMS the first time they are executed, therefore increasing performance Prepared statements are immune to SQL injection attacks Prepared statements free us from explicitly adding single quotes (') to our SQL statements to handle character values The java.sql.PreparedStatement interface has two methods that are very frequently used to send queries to the database: executeQuery() and executeUpdate(). The executeQuery() method is used to issue select statements to the database and returns an instance of java.sql.ResultSet containing the rows returned from the query. The executeUpdate() method is used to issue insert, update, and delete statements to the database. It returns an int value corresponding to the number of rows affected by the query. In the following sections, we illustrate database interaction through these two methods.
Entity relationships
In the previous section, we saw how to retrieve, insert, update, and delete single entities from the database. Entities are rarely isolated; in the vast majority of cases, they are related to other entities. Entities can have one-to-one, one-to-many, many-to-one, and many-to-many relationships. For example, in the CustomerDB database, there is a one-to-one relationship between the LOGIN_INFO and CUSTOMERS tables. This means that each customer has exactly one corresponding row in the LOGIN_INFO table. There is also a one-to-many relationship between the CUSTOMERS table and the ORDERS table. This is because a customer can place many orders. Additionally, there is a many-to-many relationship between the ORDERS table and the ITEMS table. This is because an order can contain many items and an item can be found in many orders. In the next few sections, we discuss how to establish relationships between JPA entities.
One-to-one relationships
One-to-one relationships occur when an instance of an entity can have zero or one corresponding instance of another entity. One-to-one entity relationships can be bidirectional (each entity is aware of the relationship) or unidirectional (only one of the entities is aware of the relationship). In the CUSTOMERDB database, one-to-one mapping between the LOGIN_INFO and CUSTOMERS tables is unidirectional, as the LOGIN_INFO table has a foreign key to the CUSTOMERS table, but not the other way around. As we will soon see, this fact does not stop us from creating a bidirectional one-to-one relationship between the Customer entity and the LoginInfo entity.
One-to-many relationships
With JPA, one-to-many entity relationships can be bidirectional (one entity contains a many-toone relationship and the corresponding entity contains an inverse one-to-many relationship). With SQL, one-to-many relationships are defined by foreign keys in one of the tables. The "many" part of the relationship is the one containing a foreign key to the "one" part of the relationship. One-to-many relationships defined in an RDBMS are typically unidirectional, as making them bidirectional usually results in denormalized data. Just like when defining a unidirectional one-to-many relationship in an RDBMS, in JPA the "many" part of the relationship is the one that has a reference to the "one" part of the relationship. Therefore, the annotation used to decorate the appropriate setter method is @ManyToOne.
Many-to-many relationships
In the CUSTOMERDB database, there is a many-to-many relationship between the ORDERS table and the ITEMS table. We can map this relationship by adding a new Collection<Item> field to the Order entity and decorating it with the @ManyToMany annotation.
Criteria API
One of the main additions to JPA in the 2.0 specification is the introduction of the Criteria API. The Criteria API is meant as a complement to the Java Persistence Query Language (JPQL). Although JPQL is very flexible, it has some problems that make working with it more difficult than necessary. For starters, JPQL queries are stored as strings and the compiler has no way of validating JPQL syntax. Additionally, JPQL is not type safe. We could write a JPQL query in which our where clause could have a string value for a numeric property and our code would compile and deploy just fine. To get around the JPQL limitations described in the previous paragraph, the Criteria API was introduced to JPA in version 2.0 of the specification. The Criteria API allows us to write JPA queries programmatically, without having to rely on JPQL.
Another new feature introduced in JPA 2.0 is support for JSR 303, Bean Validation. Bean Validation support allows us to annotate our JPA entities with Bean Validation annotations. These annotations allow us to easily validate user input and perform data sanitation.
Summary
This chapter covered how to access data in a database via both the Java Database Connectivity (JDBC) and through the Java Persistence API (JPA). We covered how to obtain data from the database by using JDBC via the executeQuery() method defined in the java.sql.PreparedStatement interface. We also covered how to insert, update, and delete data in the database via the executeUpdate() method defined in the same interface. Additionally, using dependency injection to inject a DataSource into an object was also covered. Setting a Java class as an entity by decorating it with the @Entity annotation was also covered. Additionally, we covered how to map an entity to a database table via the @Table annotation. We also covered how to map entity fields to database columns via the @Column annotation, as well as declaring an entity's primary key via the @Id annotation. Using the javax.persistence.EntityManager interface to find, persist, and update JPA entities was also covered. Defining both unidirectional and bidirectional one-to-one, one-to-many, and many-to-many relationships between JPA entities was covered as well. Additionally, we covered how to use JPA composite primary keys by developing custom primary key classes. We also covered how to retrieve entities from a database by using the Java Persistence Query Language (JPQL). We then discussed some new JPA 2.0 features such as the Criteria API that allows us to build JPA queries programmatically, the Metamodel API that allows us to take advantage of Java's type safety when working with JPA, and Bean Validation that allows us to easily validate input by simply annotating our JPA entity fields