Persistence - Java EE and HTML5 Enterprise Application Developmentb (2014)

Java EE and HTML5 Enterprise Application Developmentb (2014)

CHAPTER

2

Persistence

Data is an integral part of any application and typically defines the state of an application at any given point of time. Persistence is the characteristic of an application state that outlives the process that created it. Absent persistence, application data would be lost when the application terminates. If a banking application could not persist information about the accounts, that application would be useless. Similarly, if a retail store application could not persist information about the inventory, customer orders, and shipments, it would be of no value. Persistence allows applications to access the data and perform CRUD (create, read, update, and delete) operations that change the data’s state. After an application crashes unexpectedly and then recovers, persistence enables the application to use the data in the exact state that it was in at the time of the crash.

There are many ways to persist data in Java. Java Platform, Standard Edition (Java SE) provides APIs to manipulate streams and files. This requires lots of low-level handling, such as defining the stream location and names, opening and closing streams, and defining a data format. The Java Database Connectivity (JDBC) API can be used to store data to a relational database such as an Oracle or MySQL database server. This requires managing database connections, writing SQL queries, mapping results with Java objects, and a lot more. Different NoSQL data stores provide APIs to manage data specific to those data stores. The majority of data is persisted in databases, specifically relational databases.

The Java EE platform provides the Java Persistence API (JPA) for the management of persistence and object/relational mapping. In other words, a POJO (Plain Old Java Object) can be used to represent a table in the relational database, and each class instance corresponds to a row in that table. The API defines how these rows can be managed using the POJO.

Data stored in a relational database should maintain ACID (atomicity, consistency, isolation, durability) properties. To help ensure that ACID properties are maintained, it is very important to ensure that any addition, update, or deletion of data is done within a transactional boundary. The transactions can be container-managed or user-managed. Container-managed transactions can be managed either by the Enterprise JavaBeans (EJB) container or by using the @javax.transaction.Transactional annotation provided by the Java Transaction API (JTA). In this case, a transaction is automatically started by the container and then either committed or rolled back by the container. A user-managed transaction is explicitly started and completed by the user. In this case, the application explicitly starts the transaction and then either commits or rolls back the transaction before exiting out of the method.

This chapter will introduce the main concepts of JPA, how an entity can be created, queried, and updated. Text-based Java Persistence Query Language (JPQL) and type-safe Criteria API are explained. Container-managed transactions that preserve the ACID properties of these entities are explained. Finally, database schema generation using persistence properties is explained. NetBeans IDE tools and wizards are explained in reference to context throughout the chapter.

JPA Entity

JPA defines an entity as a lightweight persistent domain object. Any POJO with a no-args public constructor can be defined as an entity. A JPA entity defining the concept of an author is shown in Listing 2-1.

image

Listing 2-1 Author Entity

image

image

Let us walk through this code:

image @javax.persistence.Entity annotation on a POJO specifies that this is an entity. The default name of the entity is the unqualified name of the class. An optional name attribute may be used to specify the entity name, which is then used to refer to the entity in queries.

image @javax.persistence.Table is an optional annotation on an entity and specifies the primary table for the annotated entity. Additional tables may be specified using SecondaryTable or SecondaryTables annotation.

If no @Table annotation is specified on the entity, or the annotation is specified but no name attribute is specified, then the generated table defaults to the entity name.

image Implementing the Serializable interface allows the class to be passed by value through a remote interface.

image The properties of the bean that follow the JavaBeans-style accessors (“property access”) or instance variables (“field access”) represent the persistent state of the entity. The persistent fields or properties of an entity class can be from a wide range of types, such as Java primitive types, any primitive wrapper type, other fine-grained classes defined using @javax.persistence.Embedded and known as embeddables, a collection of embeddables, and many other types.

The properties id, firstName, lastName, bio, and email have getters and setters that are omitted for brevity in this code. Each of these fields will map to a column in the database table.

Reasonable default column names are used for properties and fields. For example, the column name ID is used for the id property, and the column name FIRST_NAME is used for the firstName property. Optionally, a @javax.persistence.Column annotation may be used to override the name of the mapped column. This annotation can also use several attributes to control the definition of the mapped column.

image @javax.persistence.Id annotation specifies the primary key of an entity. The field or property to which this annotation is applied should be one of the following types: any Java primitive type, any primitive wrapper type, java.lang.String, java.util.Date, java.sql.Date,java.math.BigDecimal, or java.math.BigInteger. The corresponding mapped column is assumed to be the primary key of the primary table.

A composite primary key that consists of multiple fields or properties can be defined using @javax.persistence.IdClass annotation on an entity. An embeddable class can be denoted as the primary key using @javax.persistence.EmbeddedId annotation.

image Validation constraints can be specified on entities to ensure that only valid data is used to communicate with the database. Bean Validation 1.1, another specification in the Java EE 7 platform, defines several such predefined constraints in the javax.validation.constraints package. Specifying @javax.validation.constraints.NotNull on a field ensures that this field cannot be set to null and persisted. The @javax.validation.constraints.Size constraint allows you to specify minimum and maximum boundaries of the field.

The Bean Validation specification even defines an extensible mechanism by which you can easily define custom constraints to meet application needs.

An entity can capture the relationship between different tables using @javax.persistence.OneToOne, @javax.persistence.OneToMany, @javax.persistence.ManyToOne, and @javax.persistence.ManyToMany annotations. A join table is defined using @javax.persistence.JoinTable annotation. A collection of basic or embeddable types can be mapped using @javax.persistence.CollectionTable annotation.

NetBeans IDE provides a wizard that enables you to generate JPA entities from a database schema. In the IDE, right-click your application and choose New | Other | Persistence | Entity Classes from Database. The Database Tables page of the New Entity Classes from Database wizard is shown in Figure 2-1. The tables available in the selected data source are displayed in the Available Tables list.

image

image

image

FIGURE 2-1. Selecting tables from a database

Select any tables in the Available Tables list in the left pane and click the Add button to add them to the Selected Tables list on the right. If you add a table that references other tables, the referenced tables are automatically added to the Selected Tables list as well. The referenced tables are grayed out to indicate that they are referenced tables. The IDE will automatically generate entity classes for each of the tables listed in the Selected Tables list.

Click Next to move to the Entity Classes page of the New Entity Classes from Database wizard, as shown in Figure 2-2, where you review or set the following:

image

image

image

FIGURE 2-2. Defining classes and other files to be created

image Class Names Displays the name of the class that is generated for each table listed. The Generation Type column displays whether the class will be new, updated, or re-created. If the entity class for a selected table already exists, you can choose to either re-create the entity class or update the existing class by clicking the toggle button (…) below the Class Names table.

image Project Displays the project where the entity classes will be saved. This field is read-only.

image Location Select the source folder where you want to create the entity class.

image Package Select an existing package from the drop-down list or type the name of a new package.

image Generate Named Query Annotations for Persistent Fields If selected, the IDE generates named query annotations in the entity classes.

image Generate JAXB Annotations If selected, the IDE generates annotations in the entity class for mapping the class to an XML element that can then be used by a Java Architecture for XML Binding (JAXB) web service.

To persist entity classes, your project requires a persistence unit (as described in the following section, “Packaging an Entity”). NetBeans IDE checks if there is a persistence unit for the project when you create the entity class. If the IDE cannot locate a persistence unit, the Create Persistence Unit check box appears, as shown in Figure 2-2. Alternatively, you can create a persistence unit later by choosing Persistence | Persistence Unit in the New File wizard.

From the Entity Classes page, you can click Finish to create entity classes for each of the specified tables, or you can click Next to modify the default settings used when generating the mapping annotations, as shown in Figure 2-3. If you choose the latter option, you can set the following options for configuring generated annotation elements:

image

image

image

FIGURE 2-3. Setting options for the creation of entity classes

image Association Fetch Select the fetch element to add to the relationship annotations. You can select default, eager, or lazy. If default is selected (default is selected by default), no fetch element is added to the relationship annotations.

image Collection Type Select the collection type for OneToMany and ManyToMany Container-Managed Relationship (CMR) fields. You can select java.util.Collection, java.util.List, or java.util.Set.java.util.Collection is selected by default.

image Fully Qualified Database Table Names If selected, catalog and schema elements are added to the @Table annotation. This option is deselected by default.

image Attributes for Regenerating Database Tables If selected, nullable (when it is false), length (for String type), precision, and scale (for decimal type) are added to the @Column annotation. Unique constraints are also added to the @Table annotation if this option is selected. This option is deselected by default.

image Use Column Names in Relationships If selected, when a table references a foreign key, the field name is generated according to the name of the column in the table. For example, if the table customer has a column named zip that is mapped to a column named zip_code in tablemicromarket, the generated field name will be zip. This option is selected by default.

If this option is deselected, the field name is generated according to the name of the table that contains the foreign key. In the example shown in the previous figures, the generated field name will be microMarket.

image Use Defaults if Possible If selected, only annotations that modify the default behavior or attributes will be generated. Selecting this option can reduce the number of unnecessary annotations that are generated. This option is deselected by default.

image Generate Fields for Unresolved Relationships If selected, basic generic fields are generated for the fields in a relationship that reference fields or entities that are missing or cannot be resolved. The basic fields that are generated might not accurately represent the columns in the tables because of the missing data.

If this option is deselected, fields in a relationship are not generated if any of the fields or entities in the relationship are missing. This option is deselected by default.

When you click Finish, the IDE creates entity classes for each of the tables you specified in the wizard, as shown in Figure 2-4.

image

image

image

FIGURE 2-4. Examining the result of creating new entity classes

Packaging an Entity

An entity is managed within a persistence context, a set of managed entity instances in which any persistent entity identity has a unique entity instance. A persistence context has multiple entity managers that manage the entity instances and their life cycles. The entity managers, their configuration information, the managed entities, and optional metadata that defines the mapping of the entities to the database are together packaged as a persistence unit. A persistence unit is defined by a persistence.xml file and packaged within a WAR file. Listing 2-2 shows a samplepersistence.xml file.

image

Listing 2-2 Sample persistence.xml File

image

image

The persistence.xml file can have one or more <persistence-unit> elements, each corresponding to an entity manager. Each entity manager can be configured using several standard javax.persistence.* <properties> elements.

NetBeans IDE provides an editor for editing persistence.xml files. Open a persistence.xml file and you will see that three different views are available for working with the file: Design, Source, and History. Click the Source button to see the source of the file. When you use code completion in Source view—that is, you press CTRL-TAB (by default)—context-sensitive suggestions are shown for completing the current word, together with relevant documentation, as shown in Figure 2-5.

image

image

image

FIGURE 2-5. Source view for persistence.xml file

When you click the Design button, a structured view is shown for working with the persistence.xml file (see Figure 2-6). A drop-down list lets you navigate to sections of interest, while text fields and buttons let you enter values into the underlying persistence.xml file.

image

image

image

FIGURE 2-6. Design view for persistence.xml file

Finally, clicking the History button opens a local history view of your file. The History view lets you roll back changes that are saved locally.

Managing an Entity

Each entity goes through create, read, update, and delete (CRUD) operations during its life cycle. Typically, an entity is created once, read and updated multiple times, and then deleted once.

An Enterprise JavaBean (EJB; also known as enterprise beans) is typically used to manage the entity. An EJB instance is itself managed at runtime by an EJB container. The container provides all the plumbing, such as transactions, remoting, concurrency, connection pooling, and other such details, so that the application developer can focus on the business logic.

There are two types of EJBs: session beans and message-driven beans. A session bean processes the message synchronously, and a message-driven bean is used to process messages asynchronously. There are three types of session beans: stateful, stateless, and singleton. A stateful session bean maintains a conversational state for a specific client, a stateless session bean does not contain any conversational state for a specific client, and a singleton session bean is instantiated once per application.

A stateless session bean, by its very nature of being stateless, can be pooled by the container and provides much better scalability for the application. By default, all methods of a session bean have container-managed transactions. This means the EJB container implements all the low-level transaction protocols, such as the two-phase commit protocol between a transaction manager and a database system, to honor the transactional semantics. The changes to the underlying resources are all committed or rolled back accordingly.

A container-managed entity manager can be obtained in a stateless session bean using dependency injection. The entity manager is then used to perform operations on an entity.

Listing 2-3 shows how a stateless session bean can be used to create or delete an entity instance.

image

Listing 2-3 CRUDing Author Entity

image

image

A stateless session bean is defined by adding @javax.ejb.Stateless annotation on a POJO. To create a new row in the database table, a new entity instance is created using a no-args constructor or a convenience constructor. Calling setters or assigning instance variables then populates the entity values. This is typically done in a client component such as a servlet or any other Java EE component.

A container-managed javax.persistence.EntityManager is obtained and used within the addAuthor() method to save the entity. Similarly, an entity instance can be removed by calling the EntityManager.remove() method. The EJB container starts a transaction before the method is invoked and commits the transaction after the method completes. All changes made to the entity manager are stored in the database with a transaction commit.

NetBeans IDE provides a wizard that enables you to generate EJBs. In the IDE, right-click your application and choose New | Other | Enterprise JavaBeans | Session Bean to open the New Session Bean wizard, shown in Figure 2-7.

image

image

image

FIGURE 2-7. Creating new session beans

For Session Type, you can select one of the following:

image Stateless The bean does not save state information during its conversation with the user. These enterprise beans are useful for simple interactions between the client and the application service, interactions that are complete in a single method invocation. An example is an enterprise bean that processes orders. Each order can be processed by an invocation of one method, such as processOrder(). All the information needed for processing is contained in the method parameters.

image Stateful The bean saves state information during its conversation with the user. These enterprise beans are useful for business processes that require an interaction between a client and application service that lasts longer than a single method invocation and requires memory of the state of the interaction. An example is an online shopping cart. The end user, through the client program, can order a number of items. The stateful session bean managing the interaction must accumulate items until the end user is ready to review the accumulated order, approve or reject items, and initiate processing of the lot. The stateful session bean has to store the unprocessed items and enable the end user to add more.

image Singleton A singleton session bean is instantiated only once per application and exists for the life cycle of the application. You can create a singleton bean that the container instantiates when the application starts up by using the @Startup annotation. An example is a bean that is used to initialize data for an application that can be concurrently accessed by many clients.

An alternative to using an EJB container providing container-managed transactions is to use the newly introduced @javax.transaction.Transactional annotation on a POJO or its method. This allows declarative definition of transaction boundaries on beans managed by Contexts and Dependency Injection (CDI), as well as classes defined as managed beans or other Java EE components. The transactional semantics are implemented using CDI interceptor bindings.

Listing 2-4 shows how @javax.transaction.Transactional annotation can be specified on a method to create or delete an entity instance. Just like in EJB, a container-managed transaction is automatically started by the CDI runtime and committed or rolled back, as appropriate.

image

Listing 2-4 Author with @Transactional

image

image

Java Persistence Query Language

Java Persistence Query Language (JPQL) is a string-based query language used to define queries over entities and their persistent state. JPQL allows the application developer to specify the semantics of queries in a portable way. The underlying persistence provider converts the query language to a target language, such as SQL, of a database or a persistent store.

A query may be a SELECT statement (R from Read of CRUD), UPDATE statement (U from Update of CRUD), or DELETE statement (D from Delete of CRUD). An optional WHERE clause can be used to restrict the results, and a GROUP BY clause, HAVING clause, or ORDER BY clause can be used to aggregate the results. The query may be constructed dynamically or may be statically defined in a metadata annotation.

As shown in the following example, @javax.persistence.NamedQueries annotation can be used on an entity to specify multiple named JPQL queries. Each query is specified using @javax.persistence.NamedQuery annotation. Each query requires a name attribute to uniquely identify the query within the persistence unit. The query string is defined using the query attribute.

image

image

In the preceding example, both the queries are statically defined. The first query has the name Author.findAll and is equivalent to selecting all rows from the table. Note that the query string is defined around the entity, and not the corresponding database table. This is what provides portability of JPQL over multiple databases. The second query has the name Author.findById, uses a WHERE clause to restrict the result set, and requires a parameter id to be specified.

NetBeans IDE provides a JPQL Query dialog so that you can verify queries without deploying the application. Before you use it, make sure to compile the JPA entities in your application, since these compiled classes are used by the JPQL Query dialog. Then, as shown in Figure 2-8, right-click the persistence.xml file and choose Run JPQL Query to open the JPQL Query dialog.

image

image

image

FIGURE 2-8. Opening the JPQL Query dialog

In the JPQL Query dialog, you can use code completion, CTRL-TAB (by default), to help you define your queries. When you run a query, the results are shown in the Result tab, as shown in Figure 2-9, while the SQL version of the query is available in the SQL tab.

image

image

image

FIGURE 2-9. Showing query results

Criteria API

The javax.persistence.Criteria API is an object-based, type-safe alternative to string-based JPQL. It operates on a metamodel of the entities, which is typically generated by an annotation processor. The metamodel is a set of classes that describes your domain model and provides a generic way to deal with an application’s domain model. The APIs in the package, javax.persistence.criteria and javax.persistence.metamodel, are used to create this strongly typed query.

Listing 2-5 shows how you can write the Author.findAll query using the Criteria API.

image

Listing 2-5 Author Criteria Query

image

image

The Criteria query is verbose but provides a lot more flexibility in constructing dynamic queries.

Native SQL

In certain cases, a native SQL statement may have to be used to query the database. The javax.persistence.EntityManager.createNativeQuery() method can used to specify the native SQL query string. Listing 2-6 shows how the Author.findAll named query can be executed as a native SQL query.

image

Listing 2-6 Author Native Query

image

image

In this simplified case, the result set is mapped directly to the Author entity class. More complex mappings can be specified using the @javax.persistence.SQLResultSetMapping annotation.

NetBeans IDE provides wizards to query the database using native SQL query strings. Switch to the Services window (CTRL-3) and expand the Databases node. Right-click a table node, as shown in Figure 2-10, and choose View Data to view data in the related table in the database.

image

image

image

FIGURE 2-10. Viewing data defined in a database

When the SQL editor opens, you have syntax coloring and code completion available to query the database and view the data directly in the IDE, as shown in Figure 2-11.

image

image

image

FIGURE 2-11. Editing SQL query strings in the SQL editor

A row from the database table can be removed by retrieving the required entity using any method. The javax.persistence.EntityManager.remove() method is called to remove the entity. Like the javax.persistence.EntityManager.persist() method, it must be called within a transaction. The entity’s state is persisted to the database when the transaction is committed, either implicitly by the container or explicitly by the user.

NetBeans IDE provides a wizard to generate JPA controller classes that perform CRUD functionality for an entity class. In the IDE, right-click your application and choose New | Other | Persistence | JPA Controller Classes from Entity Classes.

In addition, you can generate session beans for the entity classes in the application. In the IDE, right-click your application and choose New | Other | Enterprise JavaBeans | Session Beans for Entity Classes, which displays the New Session Beans for Entity Classes wizard page shown inFigure 2-12.

image

image

image

FIGURE 2-12. Getting started creating session beans for existing entity classes

Select any entity classes from the Available Entity Classes list in the left pane, and click the Add button. Any referenced entity classes are automatically added to the Selected Entity Class list in the right pane. If an entity class is grayed out, that indicates it is a referenced entity class.

Click Next to move to the Generated Session Beans page of the wizard, shown in Figure 2-13, and review or set the following:

image

image

image

FIGURE 2-13. Specifying details for creating session beans

image Project Displays the project where the entity classes will be saved. This field is read-only.

image Location Select the source folder where you want to create the entity class.

image Package Select an existing package from the Package drop-down list or type the name of a new package.

image Create Interfaces Select the session facade interfaces that you want the wizard to generate.

When you click Finish, the specified session beans are created, as shown in Figure 2-14.

image

image

image

FIGURE 2-14. New session beans created in the application

Schema Generation

Typically, the database schema is already defined and JPA entity classes can be generated from that. Alternatively, entity managers can be configured to generate database table definitions in an existing schema or table generation scripts by specifying javax.persistence.schema-generation.*properties in persistence.xml.

Listing 2-7 shows how these properties can be configured on an entity manager.

image

Listing 2-7 Generating Schema Using persistence.xml

image

image

The following list explains these properties:

image The javax.persistence.schema-generation.database.action property value specifies to drop the existing tables and create them again. The possible values are none, create, drop-and-create, and drop.

image The javax.persistence.schema-generation.create-source property value specifies that the database creation should occur on the basis of the scripts.

image The javax.persistence.schema-generation.drop-source property value specifies that the database deletion should occur on the basis of the scripts.

The possible values for the preceding two properties are metadata, script, metadata-then-script, and script-then-metadata. In this case, either script or metadata specified on the entity or a combination is used to create or drop tables.

image The javax.persistence.schema-generation.create-script-source property value specifies the location of the database creation script.

image The javax.persistence.schema-generation.drop-script-source property value specifies the location of the database deletion script.

image The javax.persistence.sql-load-script-source property value specifies the location of SQL bulk load script.

The last three property values specify that the script be packaged with the application. In this case, the location of the script is specified relative to the root of the persistence unit. Alternatively, a URL may externally identify the scripts.

These properties enable generation of the database schema from scripts or entity metadata. In addition to the properties described previously, the following properties may be used to specify the generation of scripts:

image javax.persistence.schema-generation.scripts.action can be used to specify which scripts need to be generated. The possible values are none, create, drop-and-create, and drop.

image javax.persistence.schema-generation.scripts.create-target and javax.persistence.schema-generation.scripts.drop-target can be used to specify the location of create and drop scripts. The locations are specified as strings corresponding to file URLs.

JPA provides several annotations such as @javax.persistence.Index, @javax.persistence.ForeignKey, @javax.persistence.CollectionTable, @javax.persistence.JoinTable, and @javax.persistence.JoinColumn that can be specified on an entity to facilitate database or scripts generation.

NetBeans IDE provides a wizard that simplifies the generation of scripts based upon metadata. In the IDE, right-click your application and choose New | Other | Persistence | DB Scripts for Entity Classes to generate the scripts.

The Java Persistence API also provides a mechanism for second-level caching, optimistic and pessimistic locking, entity lifecycle listeners, and many more advanced concepts.

Summary

This chapter described the key concepts of persistence and explained how data can be created, read, updated, and deleted from a relational database using JPA. It also looked at how relational database tables can be easily mapped to JPA entities, and it presented the requirements around their packaging. Different types of Enterprise JavaBeans were introduced and their transactional nature was explained briefly. Finally, this chapter demonstrated how the database tables can be easily generated using the properties defined in persistence.xml. NetBeans IDE tools and wizards were shown throughout the chapter to highlight the simplified development process. The next chapter will take these JPA entities and publish them as RESTful endpoints.

image