Sei sulla pagina 1di 243

Preparing for EJB 3.

You don't have to look far to see how excited people are about the new direction EJB 3.0 is
taking. In fact, the entire J2EE component suite has a mandate to simplify the development
process, and we can all look forward to a time when it will be much easier to develop, test and
deploy our enterprise applications. EJB 3.0 is taking ease of development extremely seriously
and has adjusted its model to offer the kind of POJO (Plain Old Java Object) persistence that
TopLink has been doing for a decade.

This is no coincidence as the specification lead, Linda DeMichiel, chose to look outward for
advice and experience from products like TopLink. This allowed the specification to follow the
trails that had already been blazed by popular and proven technologies, and that had in fact
become de facto practices in the industry. The EJB specification can now proudly claim that it
is transitioning back to becoming both a relevant and a useful persistence specification
because it is in harmony with what the vast majority of applications are already doing.

Work on the specification is progressing rapidly, and as a strong supporter of the new EJB
model Oracle is actively participating in this process. Not only are we a major technical
contributor but we are also currently preparing to offer a preview release of the EJB 3.0
Container technology.

Recognizing the fact that previews are not typically going to be suitable for deploying
applications into production, and that the final release of EJB 3.0 will likely be sometime next
year, the question arises - I like what I see, but what can I do now? The answer is that you can
be proactively preparing your application for EJB 3.0. When the final draft of the specification
rolls off the presses you will want your application to be in a state where it is a simple matter
to migrate to the new persistence standard. Even better, you would like your application to
already be using some of the features offered by the standard. In this paper I will explain how
this can be done, and give advice about which features to use so that you can not only be ready
for EJB 3.0, but already be most of the way there.

Get Your Architectural House in Order

The first step is to ensure that your architecture makes use of standard and accepted design
patterns around persistence. This may actually require changes to your application, but is well
worth the investment if you expect your application to endure the test of time. Using session
facades, DAO (Data Access Object) layers or service layers are always good ideas, but in this
case they are critical. Although not commonly done, if your application is already built using
remote entities then you will need to rework your architecture. A remotable service layer is
expected to be in place before persistence objects are accessed. If entities are being used then
they should strictly be of the local variety.

Using local entities is not the end, however, since entities also provide deployers with the
ability to declaratively state the transactional and security requirements for the entity. EJB 3.0
will not allow any of these attributes to be set at the entity level. Instead, the context in which
entities will run will be determined by the caller, so any transactional or security context that
is required should be installed or declared by its enclosing J2EE component. This separates
the largely orthogonal issues of persistence from the rest of the distributed component model.
CMP Applications
If you are already a CMP user then you may be thinking three things. First, you can't wait to
get the new features and are ecstatic about ditching the extraneous interfaces, unnecessary
bean code and tedious XML deployment descriptors that were some of the annoyances
associated with previous entity bean development. The remote and local interfaces that had to
extend EJBObject and EJBLocalObject, respectively, are no longer required and entities may
now, if they choose to, simply implement a plain old Java interface (POJI).

Secondly, you are probably dreaming about how you will be able to more easily deploy your
EJB's in the container, or even not deploy them at all but test them outside the container in a
standalone environment. Because the entities are concrete plain old Java objects (POJO's), you
will be able to create them the way that you always created Java objects, using new().

Lastly, you may be wondering how hard it will be to migrate some of your existing 2.1 style
beans to use the new 3.0 style of programming. This is a concern that Oracle is taking to heart.
In fact, we firmly believe that the strength of the transition strategy offered by a EJB product
will be one of the main criteria that applications use when it comes time to choose their EJB
3.0 implementation. Our goal is to make this transition as easy as possible and we are
planning and developing our implementation around this goal.

POJO Applications

The bulk of the new persistence API is accessible from the EntityManager, which may be
injected into a session bean or looked up in JNDI. The EntityManager represents the
transactional persistence context, which maps very closely to the TopLink UnitOfWork. Any
objects managed by the UnitOfWork, or EntityManager, that are found to be dirty at the end of
the transaction will be written out to the data store.

An application can insulate itself from extensive changes by abstracting the code that obtains
the UnitOfWork/Session artifacts. This way the actual session that gets used can be obtained
in a pluggable way. Defining the session and then allowing a surrounding layer to set it from
the outside would be similar to the dependency injection paradigm that has been adopted by
the EJB 3.0 Container. This pattern should be followed for all resources that are used in the
application. In EJB 3.0 standard resources will be declared by the application and
subsequently injected into the bean at runtime.

Adopt Standard Features

Many of the EJB 3.0 features will be recognizable in features that have been around in TopLink
for a long time. By using these features you will be able to have the functionality of EJB 3.0
even though the API's are not yet completed.

Querying is one such area where you can start using EJB 3.0 features right now. TopLink
provides the ability to define and execute named queries. Configuration of queries may be done
statically or dynamically to allow just-in-time querying with client-based criteria.

EJB 3.0 queries will be obtained from the EntityManager, and will be executable on it. It will be
possible to create a native SQL query for the rare cases when you need to go directly to SQL,
and get objects back from the query. TopLink has custom queries that do exactly that, and
they perform the mapping of the result set data to objects.

Query languages are often the source of migration headaches because it is very difficult to
translate automatically without writing a substantive or exhaustive translation parser tool.
EJB QL is a reasonable and sufficient abstraction of a relational query language and will
benefit from the several new features that are being added to it. Existing EJB QL will apply and
still more EJB QL constructs and functions will enhance the query language further. Even
though the query API's may not be released yet, it would make sense to write queries using
EJB QL since the query language is not going to change substantially, except in an additive
way. TopLink supports using EJB QL with POJOs, thus helping an application to get to a state
where it is able to port its queries over to another database, another framework, or another
persistence API.

Inheritance

True and natural inheritance, as Java objects were built to support and participate in, was
never specified in EJB 2.1. In practice, inheritance was only possible if the vendors did not
throw up obstructions, but was still quite difficult to define and manage. This will not be the
case in EJB 3.0. With concrete Java objects being able to inherit from each other, and not be
required to define methods that handcuffed the extent of the inheritance, you will be able to
create entity inheritance hierarchies arbitrarily deep and wide.

This same flexibility is currently achievable from both within the TopLink Mapping Workbench
or JDeveloper, GUI tools for mapping Java objects, as well as in the Java-based API for
mapping objects. Your domain model can be produced now to adhere to the inheritance
strategy that suits your application without having to wait for the specification to be released.

Optimistic Locking

The optimistic locking model that TopLink strongly supports is now going to be adopted into
the EJB 3.0 model. This is a very good thing for applications, not only because it will offer huge
increases in performance in the face of normal 90/10 read/write access ratios, but because it
leads to the kinds of scalable architectures that modern systems require. This is a key locking
paradigm that is already used by thousands of applications in the industry to achieve the
scalability that web applications demand.

The flexibility of the TopLink options for locking values, and how they are determined,
computed and stored, supercedes those included in the EJB 3.0 specification. The basics are
clear, however, and portability is easily achieved by making use of the straightforward
approach of a database column and object version field for each optimistically locked object.

This type of locking provides the added benefit of being able to use the objects in disconnected
modes. Modifying data and relationship while offline can be easily supported simply by merging
the data back into a transaction and verifying through the optimistic lock value that the object
that was modified was not a stale copy. This aligns perfectly with what TopLink users are
already doing when they merge their objects back into a unit of work.

Event Callback Listeners

The EJB model of life cycle callbacks is being adapted in two useful ways. The first is that the
callbacks are more relevant to the O/R mapping runtime execution model and fine-grained
events such as insertion in the database will enable actions to be taken to perform things such
as auditing and other book-keeping. Secondly, non-bean event listeners can register to handle
the event callbacks. This means that when you use the TopLink event listeners that you are
already using the model that EJB 3.0 entities have now embraced.
Object-Relational Mappings

Perhaps the most obvious and visible support that has been provided by TopLink over the
years is the ability to map object data and their relationships to relational tables. This has been
a critical problem that has plagued applications that want to write object-oriented Java
programs but store their data in relational databases.

The decision to add standardized metadata and semantics for object-relational mappings into
EJB 3.0 is a giant step towards allowing applications the flexibility to take their application and
run it on different databases and even use different persistence frameworks to do so. The first
pass at the O-R mapping standard will include the most popular mappings that people now
use to map their domain models, such as basic data conversion, one-to-one and many-to-many
relationships, and so forth. Subsequent drafts will add more of the "deluxe" mappings that
TopLink already offers, so as the specification matures it will approach even closer to TopLink
as a portable solution for applications even if they have exceptional requirements.

Summary

Over the past 10 years TopLink has been incorporating the requirements of its large customer
base and evolving with the way that applications persist their objects. Now that EJB 3.0 is
modernizing its approach to persistence to align itself with what the majority of applications
are doing, TopLink customers that have been doing POJO-based persistence for years can feel
both justified and confident that standards are following their lead. Because the TopLink model
is being held up as an example of how people are happy with a persistence framework, the
features can be used as a step towards reaching the EJB 3.0 standard. In other words,
applications that want to start now to implement EJB 3.0 can use a stable and proven product
to do so, even though the specification may still be in its infancy.

TopLink is fully committed to EJB 3.0, and helping our customers move to get there. Not only
will we offer migration assistance to existing TopLink customers but we are making plans to
help applications that are based on other technologies as well. Stay tuned for more articles,
seminars and talks about how you can benefit from adopting EJB 3.0 persistence in your
applications.



An Introduction to the Enterprise JavaBeans 3.0 (EJB 3) Specification
The Enterprise JavaBeans (EJB) technology is a J2EE technology for the development and
deployment of component-based business applications. Applications written using the
Enterprise JavaBeans architecture are scalable, transactional, and multiuser secure.

In spite of the rich features, however, the complexity of the EJB architecture has hindered its
wide adoption. Competing technologies are making inroads in the EJB space. For example,
O/R mapping technologies such as Toplink and the open-source Hibernate framework have
overtaken EJB as the preferred choice for developing persistence solutions. The introduction of
the EJB 3.0 specification is a giant step forward and will go a long way toward luring
developers back to EJBs. The goal of the specification is twofold:
x Make it easier for developers to develop EJBs.
x Standardize the persistence framework.

EJB 3.0 brings us closer to the dream of treating enterprise beans like regular JavaBeans. It
decreases the number of programming artifacts for developers to provide, eliminates or
minimizes callback methods required to be implemented, and reduces the complexity of the
entity bean programming model and O/R mapping model. With EJB 3.0, J2EE now seems
accessible to a much wider audience.
In this article, we first briefly discuss the limitations of EJB 2.1. Next, we describe how EJB 3.0
addresses these difficulties by describing the proposed significant changes one by one,
including the impact on types of enterprise beans, the O/R mapping model, the entity-
relationship model, and EJB QL (EJB Query Language). We conclude with code examples using
EJB 3.0-based enterprise beans.

Limitations of EJB 2.1


Developing EJBs with EJB 2.1 hasn't been the easiest thing to do. The reasons are easy to find:
x To create a single EJB you need to create a multitude of XML deployment descriptors.
x A set of three source files must be created.
x Multiple callback methods must be implemented that usually are never used.
x You have to throw and catch several types of unnecessary exceptions.
x Yet another complaint is that the EJBs are completely untestable outside the context of
the container since components like container-managed entity beans are abstract
classes.
x Finally, EJB-QL in its current form is limited in functionality and difficult to use. These
limitations force developers to use straight JDBC and SQL, or to use other persistence
frameworks such as Toplink and Hibernate.

The sheer verbosity of the API has been one big annoyance, and EJB 3.0 makes a significant
attempt to address most issues. This article covers the important aspects of this specification.

The End of the Road for Deployment Descriptors


The configuration of XML deployment descriptors was a major bottleneck in the path to
simplifying development of EJBs. Therefore one of the primary goals of the EJB 3.0
specification was to shield the developer from having to work with XML files. This is
accomplished by the use of metadata annotations that have been added to JDK 5.0 as part of
the JSR 175 JCP specification. Annotations are a kind of attribute-oriented programming and
are similar to XDoclet. However, unlike XDoclet, which requires pre-compilation, annotations
are compiled into the classes by the Java compiler at compile-time. From the developer's point
of view, annotations are modifiers like public/private and can be used in classes, fields, or
methods:
import javax.ejb.*;

@Stateless

public class MyAccountBean implements MyAccount

{
@Tx(TxType.REQUIRED)

@MethodPermission({"customer"})

public void deposit(double money) {...}

The annotations generally are self-explanatory. The @Stateless annotation indicates that the
bean is stateless. The @Tx attribute specifies the transactional demarcation for the method,
and the @MethodPermission attribute specifies the users who are allowed to access the
method. So this means that there's no longer a need to write XML deployment descriptors to
describe these properties. However, this does not eliminate the use of XML; it just makes it
optional. The specification allows the use of XML deployment descriptors to override these
annotations.

POJO Programming Model


The critical point to note is that the above stateless session bean example is complete in itself.
Disregarding the annotations, this file is a JavaBean, also known as a Plain Old Java Object
(POJO). Interfaces are optional for entity beans and required for session beans and message-
driven beans. However, that does not mean that you have to define an interface for your
session bean or message-driven bean. If you do not implement an interface, a bean interface
will be generated for you. The type of generated interface, either local or remote, is dependent
on the annotation you used in the bean class. All the public methods of the bean class will be
included as part of the automatically generated business interface:

public interface ShoppingCart

{
public void purchase(Product product, int quantity);
public void emptyCart();
}

It is recommended that you generate the interface explicitly if you want to pick and choose the
methods of the interface that should be exposed to the client, or want to give the interface a
name different from the automatically generated name.

This interface class is a Plain Old Java Interface (POJI). Both the interface and the bean class
do not have to throw unnecessary exceptions such as RemoteException.
Callback Methods

In the EJB 2.1 specification, the developer had to implement a variety of callback methods in
the bean class, such as ejbActivate(),ejbPassivate(), ejbLoad(), and ejbStore(), most of which
were never used. With 3.0, there is no compulsion to implement any of these methods. In EJB
3.0, bean developers do not have to implement unnecessary callback methods and instead can
designate any arbitrary method as a callback method to receive notifications for life cycle
events. Any callback method has to be annotated with one of the pre-defined life cycle event
callback annotations. Examples of life cycle event callback method annotations
include PostConstruct, PreDestroy,PostActivate, or PrePassivate. Some of the event callback
methods are common to all types of enterprise beans, while some are specific to bean types
such as PostPersist for entity beans.

Callback methods can be defined either in the bean class itself or in a bean listener class. A
bean listener class is denoted using theCallbackListener annotation on the bean class with
which it is associated. The annotations used for callback methods are the same in both cases;
only the method signatures are different. A callback method defined in a listener class must
take an object as a parameter, which is not needed when the callback is in the bean itself. This
object parameter can be used to pass the bean instance to the method in the listener class.
Here's an example of putting a callback method in an entity bean:

@Entity
public class AccountBean{
@PostPersist insertAccountDetails(AccountDetails accountDetails)
public void createAccount(){}
}

Let's look at an example of creating a listener class and adding it to a bean class. The following
code defines the callback listener AccountListener:

/* Adds callback listener to bean class */


@CallbackListener AccountListener
public class AccountBean{
public void createAccount(){}
}

The following code will add the callback listener AccountListener to the Account Bean:

/* Callback method defined inside a Listener class*/


public class AccountListener{
@PostPersist insertAccountDetails(
AccountDetails accountDetails){}
}

Since the @PostPersist is used to register a method to be called on an object that has just been
inserted into the database, in this case, the method insertAccountDetails() will be invoked every
time as soon as an account has been inserted using the createAccount()method in
the AccountBean.
Configuration by Exception

The "Configuration by Exception" approach is the guiding methodology used in all aspects of EJB 3.0 to
simplify the development effort. The intent is to simplify things for developers by forcing them to code
things only where defaults are not adequate.

For instance, in many cases, defaults can be used instead of explicit metadata annotation elements. In
these cases, a developer doesn't have to specify a metadata annotation to obtain the same result as if the
annotation was fully specified. For example, by default, an entity bean (annotated by @Entity) has a
default entity type of CMP, indicating that it has container-managed persistence. These defaults can make
annotating enterprise beans very simple. The defaults always represent the most common specifications.
For example, container-managed transaction demarcation (where 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. Similarly a default business interface is generated for session and message-
driven beans which exposes all the public methods of the bean in the interface, since that is the most
common use case.

Object-relational Mapping

The O/R mapping or persistence model has significantly changed from the abstract-
persistence-schema-based approach, to one inspired by the various POJO-related approaches
en vogue today. The O/R mapping is specified using annotations. The O/R mapping metadata
expresses requirements and expectations of the application to map entities and relationship of
the application domain to the database.

In EJB 2.1, developers used their own mechanisms to do certain database-specific operations
like primary key generation. With EJB 3.0, support for several database-specific operations has
been provided. The O/R mapping model has intrinsic support for native SQL. In this article, we
do not provide details on the persistence framework, although we do provide an outline while
discussing the changes in entity beans. For details check the EJB 3.0 API specification and
download the EJB 3.0 persistence documentation.

Encapsulation of JNDI Lookups Using Annotations

EJB 3.0 addresses the encapsulation of environmental dependencies and JNDI access through
the use of annotations, dependency injection mechanisms, and simple lookup mechanisms.

The enterprise bean's context comprises its container context and its resource and
environment context. The bean may gain access to its resource references and other
environment entries in its context in two ways:

1. Having the container supply it with those references such as using injections; for
instance, @EJB public AddressHome addressHome; automatically looks up the EJB
with the JNDI name "AddressHome."
2. Use the method Object lookup(String name) that is added to
the javax.ejb.EJBContext interface. This method can be used to look up resources and
other environment entries bound in the bean's JNDI environment naming context.




Dependency Injections
A bean declares a dependency upon a resource or other entry in its environment context
through a dependency annotation. A dependency annotation specifies the type of object or
resource on which the bean is dependent, its characteristics, and the name through which it is
to be accessed.
The following are examples of dependency annotations:

@EJB(name="mySessionBean", beanInterface=MySessionIF.class)
@Resource(name="myDB", type="javax.sql.DataSource.class")

Dependency annotations may be attached to the bean class or to its instance variables or
methods. The amount of information that needs to be specified for a dependency annotation
depends upon its usage context and how much information can be inferred from that context.

Injecting arbitrary resources with @Resource


The @EJB annotation only injects EJB stubs. A more generic dependency injection annotation
is @Resource. Using the @Resource annotation, you can inject any service object from the JNDI
using the object's JNDI name. Both global (java:/) and local (java:comp/env) JNDI trees are
searched. The following examples inject a messaging connection factory and a messaging
queue:
@Resource (name="ConnectionFactory") QueueConnectionFactory factory;
@Resource (name="queue/A") Queue queue;

For "well-known" objects such as TimerService and SessionContext, the JNDI names are
standard, and therefore the @Resourceannotation can inject these objects without an explicit
specification of the "name" attribute:

@Resource TimerService tms;


@Resource SessionContext ctx;

Similar to the @EJB annotation, the @Resource annotation can be applied to setter methods,
and the @Resources annotation can be applied to arrays. Both
the @EJB and @Resource annotations are specifically tailored to the resources they inject.
They simplify the developer's work.

Code sample

In the example below, the variable customerDB will be assigned a DataSource object with JNDI
name myDB. The "name" attribute needs to be specified because the name of the variable we
have chosen, customerDB, is different from the JNDI name myDB. The "type" attribute does
not need to be specified because it can be derived from the type of the variable (for
example, DataSource):

@Stateless public class MySessionBean implements MySession {

//type is inferred from variable


@Resource(name="myDB") public DataSource customerDB;

public void myMethod1(String myString){


try {
Connection conn = customerDB.getConnection();
...
catch (Exception ex)
}
}
Changes to the Four Types of Enterprise Beans

As we all know, there are four kinds of EJBs, and needless to say, EJB 3.0 made some
changes to each type of EJB. In this section, we will look at the changes proposed for each type
of EJB. One of the main advantages is that in EJB 3.0, all the managed service objects are
POJOs (for example, session beans) or very lightweight components (such as message-driven
beans). As you'll see, EJB 3.0 has made the development of EJBs much easier and simpler.

Stateless Session Beans

An EJB 3.0 session bean is a POJO managed by the EJB container.

The functionality of a session bean is defined by its service interface (a.k.a. business interface),
which is a plain old Java interface. Using the interface class name, the session bean client
retrieves a stub object of the bean from the server's JNDI. The stub object implements the
bean's service interface. The client can then make calls to the bean interface methods against
the stub object. The stub object simply passes the calls to the actual bean instance objects in
the container, which have the implementations of those methods and do the actual work. The
stub object is automatically generated by the EJB container, and it knows how to route the
bean method calls to the container—you do not need to provide an implementation for the stub
object. In a stateless session bean, the client-side stub object can route your method call to
any bean instance that happens to be available in the container-managed object pool.
Therefore, you should not have any field variables to store the bean state in the bean class.

Business interfaces
Business interfaces are required for stateless session beans. It is not always necessary to
define one. When undefined, they will be automatically generated for you. The type of generated
interface, either local or remote, is dependent on the annotation you used in the bean class and
will be a local interface if there is no annotation. All the public methods of the bean class will
be included as part of the automatically generated business interface.

Home interfaces
Stateless session beans do not need home interfaces. The client may acquire a reference to a
stateless session bean by means of injection or annotation of variables.

Bean class
A stateless session bean must be annotated with the stateless annotation or denoted in the
deployment descriptor as a stateless session bean. The bean class need not implement
the javax.ejb.SessionBean interface. The @Stateless annotation indicates that this bean is a
stateless session bean:
@Stateless
public class TraderBean implements Trader {
public void buy (String symbol, int quantity){
System.out.println("Buying "+quantity+ " of "+ symbol);
}
public void sell (String symbol, int quantity);{
System.out.println("Selling "+quantity+ " of "+ symbol);
}
}


The session bean client
Once the session bean is deployed into the EJB 3.0 container, a stub object is created, and it is
registered in the server's JNDI registry. The client code obtains a stub of the bean using the
class name of the interface in the JNDI. Below is an example on how to retrieve a stub instance
of the TraderBean for this JSP page. You can make method calls against the stub object, and
the call is transparently delegated to the bean instance in the EJB 3.0 container:

private Trader tr = null;


public void initialize () {
try {
InitialContext ctx = new InitialContext();
tr = (Trader) ctx.lookup(
Trader.class.getName());
}catch (Exception e) {
e.printStackTrace ();
}
}
// ... ...
public void service (Request req, Response rep) {
// ... ...
double res = tr.buy("SNPS",1000);
}

Callbacks for stateless session beans


The following life cycle event callbacks are supported for stateless session beans:
x PostConstruct
x PreDestroy

The PostConstruct callback occurs after any dependency injection has been performed by the
container and before the first business method invocation on the bean.
The PostConstruct method is invoked in an unspecified transaction context and security
context.

The PreDestroy callback occurs at the time the bean instance is destroyed.
The PreDestroy method executes in an unspecified transaction and security context.

Remote and local interfaces


A session bean can also implement multiple interfaces, each interface targeting a different type
of client. By default, the interface is for a "local" client that runs in the same JVM as the EJB
3.0 container. Method call invocations over Java references are fast and efficient. Another type
of session bean interface, the remote interface, is for remote clients. When a client looks up the
session bean stub via the remote interface, the container returns a serialized stub object that
implements the remote interface. The remote stub knows how to pass remote procedure calls
(RPCs) to the server, even in a clustered environment. The remote interface is also a plain old
Java interface.

Note that using the remote interface involves the serialization and deserialization of the stub,
and all calls to the bean instance are made over the network. This approach is considerably
less efficient than using the local interface. You should avoid looking up a remote interface
from a local client.

In the session bean implementation, you can use the @Local and @Remote annotations to
specify the local and remote interfaces for this bean. Here is an example bean that implements
both a local and remote interface:
@Stateless
@Local ({Trader.class})
@Remote ({RemoteTrader.class})
public class TraderBean implements Trader, RemoteTrader {

public void buy (String symbol, int quantity){


System.out.println("Buying "+quantity+ " of "+ symbol);
}

public void sell (String symbol, int quantity);{


System.out.println("Selling "+quantity+ " of "+ symbol);
}
}
The @Local and @Remote annotations can also be used to tag session bean interfaces instead
of the bean implementation class. For instance, the following code snippet specifies that the
RemoteTrader is a remote interface. With that, you no longer need the @Remote tag
onTraderBean.
EJB 3.0 Session Beans
Stateless Session Bean Life Cycle

Implementing an EJB 3.0 Stateless Session Bean

EJB 3.0 greatly simplifies the development of stateless session beans, removing many complex
development tasks. For example:

x The bean class can be a plain old Java object (POJO); it does not need to
implement javax.ejb.SessionBean.
x The business interface is optional.

Home (javax.ejb.EJBHome and javax.ejb.EJBLocalHome) and component


(javax.ejb.EJBObject andjavax.ejb.EJBLocalObject) business interfaces are not
required.

The EJB 3.0 local or remote client of a session bean written to the EJB 3.0 API accesses
a session bean through its business interface. The business interface of an EJB 3.0
session bean is an ordinary Java interface, regardless of whether or not local or remote
access is provided for the bean.

x Annotations are used for many features.


x A SessionContext is not required: you can simply use this to resolve a session bean to
itself
x A stateless session bean does not need a remove method.

Using Annotations
You can specify an EJB 3.0 session bean class method as a life cycle callback method using
any of the following annotations:
x @PostConstruct
x @PreDestroy
x @PrePassivate (stateful session beans only)
x @PostActivate (stateful session beans only)


Stateful Session Beans

The stateful session bean is a session bean that maintains its internal states. If the client
invokes method calls against the same bean stub, the calls are always tunneled to the same
bean instance in the container. So, all field variables in the bean instance retain their values as
long as the client application retains the bean stub (or reference for a local client).

Business interface
The business interface of a stateful session bean on the EJB 3.0 API is also a plain Java
interface. Business interfaces are required for stateful session beans. It is not always necessary
to define one. When undefined they will be automatically generated for you. The type of
generated interface, either local or remote, is dependent on the annotation you used in the
bean class and will be a local interface if there is no annotation. All the public methods of the
bean class will be included as part of the automatically generated business interface.

Home interface
Stateful session beans do not need home interfaces.

Bean class
A stateful session bean must be annotated with the stateful annotation or denoted in the
deployment descriptor as a stateful session bean. The bean class does not need to implement
the javax.ejb.Session Bean interface. A stateful session bean may implement
theSessionSynchronization interface.

The implementation of the stateful TraderBean is straightforward. We annotated the


implementation class as @Stateful and used Java objects (like Integer, String) to back up the
bean properties defined in the session bean interface. The Java objects are initialized for each
bean instance when it is created, at the beginning of a client session. Below is the complete
code for the TraderBean class. It is important to note that the stateful session bean class must
implement the serializable interface so that the container can serialize the bean instances and
store them to preserve the state information when the instances are not in use.

@Stateful
public class TraderBean implements Trader, Serializable {

public String symbol = "";


public int quantity = 0;

public void buy (String symbol, int quantity){


System.out.println("Buying "+quantity+ " of "+ symbol);
}
public void sell (String symbol, int quantity);{
System.out.println("Selling "+quantity+ " of "+ symbol);
}
public String getSymbol(){
return symbol;
}
public int getQuantity(){
return quantity;
}
// Other getter methods for the attributes ...
}
The Session Bean Client
Here is a sample client:
Trader tr = null;
if (tr == null) {
try {
InitialContext ctx = new InitialContext();
tr = (Trader) ctx.lookup(
Trader.class.getName());

} catch (Exception e) {
e.printStackTrace ();
}
}

// Make use of the tr object

Callbacks for stateful session beans


Stateful session beans support callbacks for the following life cycle events: construction,
destruction, activation, and passivation. The EJB 3.0 specification defines several annotations
the bean can use to specify callback methods during the life cycle of the bean. The container
automatically calls the annotated methods at different stages of the session bean life cycle. You
can use the following annotations to tag any method in the bean class:

x @PostConstruct: The annotated method is called by the container immediately after a


bean instance is instantiated. This annotation is applicable to both stateless and
stateful session beans.
x @PreDestroy: The annotated method is called before the container destroys an unused
or expired bean instance from its object pool. This annotation is applicable to both
stateless and stateful session beans.
x @PrePassivate: If a stateful session bean instance is idle for too long, the container may
passivate it and store its state to a cache. The method tagged by this annotation is
called before the container passivates the bean instance. This annotation is applicable
only to stateful session beans.
x @PostActivate: When the client uses the passivated stateful session bean again, a new
instance is created and the bean state is restored. The method that tagged this
annotation is called when the activated bean instance is ready. This annotation is only
applicable to stateful session beans.
x @Init: This annotation designates initialization methods for a stateful session bean. It is
different from the @PostConstructannotation in that multiple methods can be tagged
with @Init in a stateful session bean. However, each bean instance can have only
one @Init method invoked. The EJB 3.0 container determines which @Init method to
invoke depending on how the bean is created (see the EJB 3.0 specification for details).
The @PostConstruct method is called after the @Init method.

Another life cycle method annotation for a stateful session bean is the @Remove tag. It is not a
callback method since the application, not the container, calls the @Remove method on the
bean stub to remove the bean instance in the container object pool.
Implementing an EJB 3.0 Stateful Session Bean

EJB 3.0 greatly simplifies the development of stateful session beans, removing many complex
development tasks. For example:

x The bean class can be a POJO; it does not need to implement javax.ejb.SessionBean.
x The business interface is optional.

Home (javax.ejb.EJBHome and javax.ejb.EJBLocalHome) and component


(javax.ejb.EJBObject andjavax.ejb.EJBLocalObject) business interfaces are not
required.

The EJB 3.0 local or remote client of a session bean written to the EJB 3.0 API accesses
a session bean through its business interface. The business interface of an EJB 3.0
session bean is an ordinary Java interface, regardless of whether or not local or remote
access is provided for the bean.

x Annotations are used for many features.


x A SessionContext is not required: you can simply use this to resolve a session bean to
itself.

Using Annotations
You can specify an EJB 3.0 session bean class method as a life cycle callback method using
any of the following annotations:
x @PostConstruct
x @PreDestroy
x @PrePassivate (stateful session beans only)
x @PostActivate (stateful session beans only)
Adapting an EJB 3.0 Stateless Session Bean for an EJB 2.1 Client

By associating an EJB 3.0 stateless session bean with EJB 2.1 home and component interfaces
(see "Using Annotations"), you can adapt an EJB 3.0 stateless session bean so that an EJB 2.1
client can access it.

You can use this technique to manage the incremental migration of an EJB 2.1 application to
EJB 3.0 or to give existing EJB 2.1 clients access to new development that you implement
using EJB 3.0.

Note:You may associate a stateless session bean with at most one remote and one local home
interface.
Note: You may associate a stateless session bean with one or more remote and local
component interfaces.

Adapting an EJB 3.0 Stateful Session Bean for an EJB 2.1 Client

By associating an EJB 3.0 stateful session bean with EJB 2.1 home and component interfaces
(see "Using Annotations"), you can adapt an EJB 3.0 stateful session bean so that an EJB 2.1
client can access it.

You can use this technique to manage the incremental migration of an EJB 2.1 application to
EJB 3.0 or to give existing EJB 2.1 clients access to new development that you implement
using EJB 3.0.

Note: You may associate a stateful session bean with at most one remote and one local home
interface.
Note: You may associate a stateful session bean with one or more remote and local
component interfaces.
Configuring Passivation

You can enable and disable passivation for stateful session beans using the server.xml file
You may choose to disable passivation for any of the following reasons:

x Incompatible object types: if you cannot represent the nontransient attributes of your
stateful session bean with object types supported by passivation (see "What Object
Types can be Passivated?"), you can exchange increased memory consumption for the
use of other object types by disabling passivation.
x Performance: if you determine that passivation is a performance problem in your
application, you can exchange increased memory consumption for improved
performance by disabling passivation.
x Secondary storage limitations: if you cannot provide sufficient secondary storage
(see "Configuring Passivation Location"), you can exchange increased memory
consumption for reduced secondary storage requirements by disabling passivation

Configuring Passivation Criteria

Configuring Passivation Location


Configuring a Life Cycle Callback Interceptor Method on an EJB 3.0 Session Bean

You can specify an EJB 3.0 session bean class method as a callback interceptor method for
any of the following life cycle events (see "Using Annotations"):
x Post-construct
x Pre-destroy
x Pre-passivate (stateful session beans only)
x Post-activate (stateful session beans only)

Note:
Do not specify pre-passivate or post-activate life cycle callback methods on a stateless session bean.

Using Annotations
You can specify an EJB 3.0 session bean class method as a life cycle callback method using
any of the following annotations:
x @PostConstruct
x @PreDestroy
x @PrePassivate (stateful session beans only)
x @PostActivate (stateful session beans only)

Configuring a Life Cycle Callback Interceptor Method on an Interceptor Class of an EJB


3.0 Session Bean

You can designate an interceptor method on an interceptor class of an EJB 3.0 session bean as
a life cycle callback interceptor method.

To configure a life cycle callback interceptor method on an interceptor class, you must do the
following:

1. Create an interceptor class.


This can be any POJO class.

2. Implement the life cycle callback interceptor method.


Callback methods defined on a bean's interceptor class have the following signature:

Object <METHOD>(InvocationContext)

3. Associate a life cycle event with the callback interceptor method (see "Using
Annotations").

A life cycle event can only be associated with one callback interceptor method, but a life
cycle callback interceptor method may be used to interpose on multiple callback events.
For example, @PostConstruct and @PreDestroy may appear only once in an interceptor
class, but you may associate both @PostConstruct and @PreDestroy with the same
callback interceptor method.

4. Associate the interceptor class with your EJB 3.0 session bean


Using Annotations
You can specify an interceptor class method as an EJB 3.0 session bean life cycle callback
method using any of the following annotations:
x @PostConstruct
x @PreDestroy
x @PrePassivate (stateful session beans only)
x @PostActivate (stateful session beans only)

Interceptor Class

public class MyStatefulSessionBeanInterceptor {


...
protected void myInterceptorMethod (InvocationContext ctx) {
...
ctx.proceed();
...
}

@PostConstruct
@PostActivate
protected void myPostConstructInterceptorMethod (InvocationContext ctx) {
...
ctx.proceed();
...
}
@PrePassivate
protected void myPrePassivateInterceptorMethod (InvocationContext ctx) {
...
ctx.proceed();
...
}
}

Configuring an Around Invoke Interceptor Method on an EJB 3.0 Session Bean

You can specify one nonbusiness method as the interceptor method for a stateless or stateful
session bean. Each time a client invokes a session bean business method, OC4J intercepts the
invocation and invokes the interceptor method. The client invocation proceeds only if the
interceptor method returns InvocationContext.proceed().

An interceptor method has the following signature:

Object <METHOD>(InvocationContext) throws Exception

An interceptor method may have public, private, protected, or package level access, but must
not be declared as final or static.

You can specify this method on the EJB 3.0 session bean class or on an interceptor class that
you associate with an EJB 3.0 session bean
Using Annotations

Example 5-5 shows how to designate a method of a session bean class as an interceptor
method using the @AroundInvoke annotation. Each time a client invokes a business method of
this stateless session bean, OC4J intercepts the invocation and invokes the interceptor
methodmyInterceptor. The client invocation proceeds only if the interceptor method
returns InvocationContext.proceed().

Example 5-5 @AroundInvoke in an EJB 3.0 Session Bean

@Stateless
public class HelloWorldBean implements HelloWorld {
public void sayHello() {
System.out.println("Hello!");
}

@AroundInvoke
protected Object myInterceptor(InvocationContext ctx) throws Exception {
Principal p = ctx.getEJBContext().getCallerPrincipal;
if (!userIsValid(p)) {
throw new SecurityException(
"Caller: '" + p.getName() +
"' does not have permissions for method " + ctx.getMethod()
);
}
return ctx.proceed();
}
}
Configuring an Around Invoke Interceptor Method on an Interceptor Class of an EJB 3.0
Session Bean
You can specify one nonbusiness method as the interceptor method for a stateless or stateful
session bean. Each time a client invokes a session bean business method, OC4J intercepts the
invocation and invokes the interceptor method. The client invocation proceeds only if the
interceptor method returns InvocationContext.proceed().

You can specify this method on an interceptor class that you associate with an EJB 3.0 session
bean or on the EJB 3.0 session bean class itself

To configure an interceptor method on an interceptor class, you must do the following:

1. Create an interceptor class.


This can be any POJO class.

2. Implement the interceptor method.


An interceptor method has the following signature:
Object <METHOD>(InvocationContext) throws Exception

An interceptor method may have public, private, protected, or package level access but
must not be declared as final or static.

3. Designate the method as the interceptor method


4. Associate the interceptor class with your EJB 3.0 session bean For more information,
see
Using Annotations
Example 5-6 shows how to specify interceptor class method myInterceptor as the interceptor
method of an EJB 3.0 session bean using the@AroundInvoke annotation. After you associate
this interceptor class with a session bean ("Configuring an Interceptor Class for an EJB 3.0
Session Bean"), each time you invoke a session bean business method, OC4J intercepts the
invocation and invokes the myInterceptormethod. The client invocation proceeds only if this
method returns InvocationContext.proceed().

Example 5-6 Interceptor Class


public class MyInterceptor {
...
@AroundInvoke
protected Object myInterceptor(InvocationContext ctx) throws Exception {
Principal p = ctx.getEJBContext().getCallerPrincipal;
if (!userIsValid(p)) {
throw new SecurityException(
"Caller: '" + p.getName() +
"' does not have permissions for method " + ctx.getMethod()
);
}
return ctx.proceed();
}

@PreDestroy
public void myPreDestroyMethod (InvocationContext ctx) {
...
ctx.proceed();
...
}
}

Configuring an Interceptor Class for an EJB 3.0 Session Bean


An interceptor class is a class, distinct from the bean class itself, whose methods are invoked
in response to business method invocations and life cycle events on the bean. You can
associate a bean class can with any number of interceptor classes.

You can associate an interceptor class with an EJB 3.0 stateless or stateful session bean.

To configure an EJB 3.0 session bean with an interceptor class, you must do the following:

1. Create an interceptor class .This can be any POJO class.


2. Implement interceptor methods in the interceptor class.
An interceptor method has the following signature:
Object <METHOD>(InvocationContext) throws Exception

An interceptor method may have public, private, protected, or package level access, but
must not be declared as final or static.

You can annotate an interceptor method as a life cycle callback or as


an AroundInvoke method

3. Associate the interceptor class with your EJB 3.0 session bean.
4. Optionally configure the session bean to use singleton interceptors.
Using Annotations
This section describes the following:
x Creating an Interceptor Class
x Associating an Interceptor Class With a Session Bean
x Specifying Singleton Interceptors in a Session Bean

Example 5-7 Interceptor Class


public class MyInterceptor {
...
@AroundInvoke
protected Object myInterceptor(InvocationContext ctx) throws Exception {
Principal p = ctx.getEJBContext().getCallerPrincipal;
if (!userIsValid(p)) {
throw new SecurityException(
"Caller: '" + p.getName() +
"' does not have permissions for method " + ctx.getMethod()
);
}
return ctx.proceed();
}

@PreDestroy
public void myPreDestroyMethod (InvocationContext ctx) {
...
ctx.proceed();
...
}
}

Associating an Interceptor Class With a Session Bean


You can associate an interceptor class with an EJB 3.0 session bean using
the @Interceptors annotation. Example 5-8 shows how to associate the interceptor class
from Example 5-7 with an EJB 3.0 session bean class.

Note that the life cycle method for @PostConstruct is a method of the EJB 3.0 session bean
class itself (for more information, see"Configuring a Life Cycle Callback Interceptor Method on
an EJB 3.0 Session Bean"), while the life cycle method for @PreDestroy is a life cycle callback
interceptor method on the interceptor class associated with this session bean (see "Configuring
a Life Cycle Callback Interceptor Method on an Interceptor Class of an EJB 3.0 Session Bean").

Example 5-8 Associating an Interceptor Class With an EJB 3.0 Session Bean

@Stateful
@Interceptors(MyInterceptor.class)
public class CartBean implements Cart {
private ArrayList items;

@PostConstruct
public void initialize() {
items = new ArrayList();
}
...
}
Specifying Singleton Interceptors in a Session Bean

As Example 5-9 shows, you can configure OC4J to use singleton interceptor classes by setting
the @StatelessDeployment or@StatefulDeployment attribute interceptorType to singleton. All
instances of this session bean will share the same instance ofMyInterceptor.
The MyInterceptor class must be stateless.

For more information about this attribute, see Table A-1. For more information on singleton
interceptors, see "Singleton Interceptors".

Example 5-9 Specifying a Singleton Interceptor Class with an EJB 3.0 Stateful Session
Bean

@Stateful
@StatefulDeployment(interceptorType="singleton")
@Interceptors(MyInterceptor.class)
public class CartBean implements Cart {
private ArrayList items;

@PostConstruct
public void initialize() {
items = new ArrayList();
}
...
}

Configuring OC4J-Proprietary Deployment Options on an EJB 3.0 Session Bean

You can configure OC4J-proprietary deployment options for an EJB 3.0 session bean using
OC4J-proprietary annotations (see "Using Annotations") or using the orion-ejb-jar.xml file
(see "Using Deployment XML").

Configuration in the orion-ejb-jar.xml file overrides the corresponding configuration made


using OC4J-proprietary annotations.

Using Annotations

You can specify OC4J-proprietary deployment options for an EJB 3.0 session bean using the
following OC4J-proprietary annotations:

x @StatelessDeployment: for stateless session beans.


x @StatefulDeployment: for stateful session beans.

Example 5-10 shows how to configure OC4J-proprietary deployment options for an EJB 3.0
stateless session bean using the@StatelessDeployment annotation.

For more information on @StatelessDeployment attributes, see Table A-1.


Example 5-10 @StatelessDeployment

import javax.ejb.Stateless;
import oracle.j2ee.ejb.StatelessDeployment;

@Stateless
@StatelessDeployment(
minInstances=5,
poolCacheTimeout=90
)
public class HelloWorldBean implements HelloWorld {
public void sayHello(String name) {
System.out.println("Hello "+name +" from first EJB3.0");
}
}

Example 5-11 shows how to configure OC4J-proprietary deployment options for an EJB 3.0
stateful session bean using the@StatefulDeployment annotation.

For more information on @StatefulDeployment attributes, see Table A-1.

Example 5-11 @StatefulDeployment

import javax.ejb.Stateful
import oracle.j2ee.ejb.StatefulDeployment;

@Stateful
@StatefulDeployment(
idletime=100
passivateCount=3
)
public class CartBean implements Cart {
private ArrayList items;
...
}

Using Deployment XML

You can specify OC4J-proprietary deployment options using the orion-ejb-jar.xml file
element <session-deployment> as Example 5-12 shows.

For more information on the <session-deployment> element, see "<session-deployment>".


Example 5-12 orion-ejb-jar.xml File <session-deployment> Element

<?xml version="1.0" encoding="utf-8"?>


<orion-ejb-jar
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="http://xmlns.oracle.com/oracleas/schema/orion-ejb-
jar-10_0.xsd"
deployment-version="10.1.3.1.0"
deployment-time="10b1fb5cdd0"
schema-major-version="10"
schema-minor-version="0"
>
<enterprise-beans>
<session-deployment
name="MBeanServerEjb"
call-timeout="0"
location="MBeanServerEjb"
local-location="admin_ejb_MBeanServerEjbLocal"
timeout="0"
...
>
</session-deployment>
...
</enterprise-beans>
...
</orion-ejb-jar>


The Jav
va Persiste
ence API - A Simpler Programm
ming Modell for Entity
y Persisten
nce

The majo or theme of version


v 5 of the Java Pla
atform, Enteerprise Edition (Java EE E, formerly
referred to
t as J2EE) is ease of de evelopment. Changes th hroughout th he platform m make the
developmment of enterrprise Java technology
t applications
a much easieer, with far le
ess coding.
Significan
ntly, these simplification
s ns have not changed thee platform's power: The Java EE 5
platform maintains all
a the functiional richneess of the preevious versio
on, J2EE 1.4 4.
se developerrs should no
Enterpris otice dramatiic simplifica
ation in Enteerprise JavaBBeans (EJB))
technolog
gy. Previous
s articles, su
uch as Introd
duction to thhe Java EE 5 Platform a and Ease of
Developm
ment in Ente erprise JavaBeans Techn nology have described th he simplifica
ations madee in
EJB 3.0 technology, an integral part of the Java
J EE 5 pllatform.

A major enhancemen
e nt in EJB technology is the addition n of the new Java Persistence API, w which
simplifiess the entity persistence model and addsa capabiilities that w
were not in E
EJB 2.1
technolog gy. The Javaa Persistence e API deals with
w the wayy relational d
data is mapped to Java
objects (""persistent entities"), the
t way thatt these objeccts are stored d in a relatio
onal databas se so
that theyy can be acce essed at a la
ater time, annd the continnued existen nce of an enttity's state e
even
after the application that uses itt ends. In ad ddition to sim
mplifying thee entity pers
sistence mod del,
the Java Persistence API standarrdizes objectt-relational m mapping.
In short, EJB 3.0 is much
m easierr to learn an
nd use than was EJB 2.1, the techn nology's previous
version, and
a should result in fasster developmment of appllications. Wiith the incluusion of the J Java
Persisten
nce API, EJB B 3.0 technology also offfers developeers an entity y programmiing model th hat is
both easiier to use annd yet richerr.

The Javaa Persistence API draws s on ideas frrom leading persistencee framework ks and APIs such
as Hiberrnate, Oraclee TopLink, and
a Java Data Objects (JDO), and d well as onn the earlierr EJB
containerr-managed persistence e. The Ex xpert Group p for the Enterprise JavaBeans 3.0
Specifica
ation (JSR 220)has
2 reprresentation from expertts in all of tthese areas as well as from
other ind
dividuals of note
n in the persistence
p community.
c

Simplicitty at a Glancce
The Javaa Persistence e API simpliffies the prog
gramming m model for entiity persisten nce and adds
s
capabilities that were not in EJB B 2.1. Here's
s a quick listt of its simpllifications an
nd additions
s:
Requires fewer classes and interrfaces
Virtually eliminates lengthy
l deplloyment descriptors thro ough annota ations
Addressees most typic cal specifica
ations througgh annotatio on defaults
Provides cleaner, eas sier, standarrdized objectt-relational m
mapping
Eliminate es the need for lookup code
c
Adds sup pport for inh
heritance, po olymorphism m, and polym morphic querries.
Adds sup pport for nammed (static) and dynamiic queries.
Provides a Java Pers sistence querry language -- an enhan nced EJB QL L
Makes it easier to tesst entities ou
utside of the
e EJB contaiiner
Can be used
u outside of the contaainer
Can be used
u with plu
uggable, thirrd-party perrsistence prooviders
This artic
cle supplements the earrlier articles by focusing g on entity-reelated code. Here you'll be
able to ex
xamine EJB B 2.1 entity beans
b in an application and comparre them to E EJB 3.0 entitties
in an equuivalent appplication. Mo
ore specificallly, you'll be able to view
w side by sidde the sourcee
code for EJB 2.1 enttity beans thhat use conta ainer-manag ged persistennce and relaationships and
compare them to the e source codde for equivalently functiioning EJB 3 3.0 entities w
written to th
he
Java Persistence APII. Note that in
i the Java Persistence
P API, what u used to be caalled entity b
beans
are now simply called entities. You'll
Y see howw much easiier and strea amlined the EJB 3.0
technologgy code is.

The artic
cle highlights
s some of th
he importantt features th at simplify tthe EJB 3.0 version of th he
code. Although this article
a focus
ses on the Ja
ava Persisten nce API and its use in a
an EJB 3.0
containerr, the API ca
an also be us
sed outside the containeer -- for insttance, in appplications fo
or the
Java Plattform, Standdard Edition
n (Java SE, formerly
fo refeerred to as J2SE). The AAPI also prov vides
support for
f pluggable, third-partty persistencce providerss. For examp ple, a persisttence
implemen ntation from
m one vendorr can be useed with an EEJB containeer from anotther vendor,
provided that the conntainer and the persiste
ence implem mentation botth conform tto JSR 220.
This artic
cle assumess that you're familiar witth the basic concepts off EJB technoology that
underlie EJB 2.1. If you're
y not, see
s the chap pter "Enterprrise Beans" in the J2EE E 1.4 Tutoria
al.
For moree informationn about EJBB 3.0 and Jaava Persisten nce conceptss, see the ch
hapter
"Enterpriise Beans" in
n the Java EE
E 5 Tutoriaal.

Contentts
- The Appplication
- The Entiities
- The Classs Definition
- Persisten
nt Fields and Properties
- Entity Id
dentity
- Relation
nships
- Inheritan
nce and Polym morphism
- Operatioons on Entitiees
- Transacttions
- Queries
- Testing Entities
E Outside of the EJB
B Container
- Summarry
- For Moree Informationn

First, let's
s look at the application
a in use.
The App
plication
This artic
cle uses the EJB 2.1 tecchnology verrsion of the a
application, the CMP Cu ustomer Sammple
Applicatiion , from th
he J2EE 1.4 samples bundle. You ca an downloadd the sample es bundle fro
om
theJ2EE 1.4 Downlo oads page. Th
he samples bundle inclu udes instrucctions for installing and
running the EJB 2.1 version of the
t applicatiion.

The EJB 3.0 version of the same e application


n is called th
he Java Persistence Dem mo and is
availablee for downloaad here. The e download bundle
b inclu
udes instrucctions for ins
stalling and
running the EJB 3.0 0 version of the
t applicatiion.
Both vers sions of the application do the same e thing: Theyy interact w
with a relationnal database to
store andd display infformation ab bout custommer subscripttions to periiodicals. Thee database stores
informatiion such as a customer''s name and d address, ass well as thee type of periiodical to wh
hich
the custoomer is subs scribed -- th
hat is, magazzine, journall, or newspaaper. You can n submit
requests to the appliication to dissplay subscrription-relatted informattion. For exaample, you can
get a list of all subsc
criptions for a particularr customer.
Figure 1 shows whatt some of the
e interaction
ns look like.
Figurre 1: Java Perrsistence Dem
mo Interactions
s

The Enttities
Let's examine the enntity-related code within the applicattion. First, let's look at w
what classes
s and
interfaces are require
ed for the en
ntities in the
e application
n. Look at Fiigure 2. Com mpare the lis
st in
the EJB 2.1 version with that off the EJB 3.0 0 version.

Figu
ure 2: Require
ed Classes an
nd Interfaces
You nee
ed to code fewer clas
sses and in
nterfaces
For an EJB 3.0 entitty, you no longer need to o code interffaces such aas LocalAdd dressHome a and
LocalAdd dress -- or even
e a deployyment descrriptor. All yo
ou need to provide is an entity class s. So
in the ap
pplication's EJB
E 3.0 verssion, what's required forr an entity h
has been redduced from th hree
classes -- for local in
nterfaces andd a businesss class -- to one entity class. This siimplification
n is
ed to entities. EJB 3.0 technology
not limite t has
h eliminateed the requiirement for a home interrface
in enterp
prise beans ofo any type. In addition, you no long ger need to iimplement
the EJBO Object and EJBLocalOb
E bject interfa
aces.For exam mple, a sesssion bean noow requires only
a bean cllass and a business
b inte
erface, whichh is a simplee Java techn
nology interfface.

The Cla
ass Definitiion
Let's now
w look at thee code for the et's start by comparing some of the key parts of the
e entities. Le
code for the
t EJB 2.1 AddressBea an class and d the EJB 3..0 Address cclass. First, w
we'll look at the
class deffinition. You can view th
he entire entiity bean classs and entity
y class by cllicking on th
heir
names inn the Figure 3.

Figure
F 3: Comp
paring Class D
Definitions

An entity is a Plaiin Old Jav


va Object (P
POJO), so n
no boilerplate is req
quired
The EJB 2.1 version of the entity s implementss the javax.ejb.EntityB
y bean class Bean interfacce. In
fact, an EJB
E 2.1 entiity bean clas
ss must impplement this interface to
o interact witth the EJB 2
2.1
containerr. Because of
o that, the bean
b class must
m also im
mplement all of the meth hods in the
interface:
ejbRemove,ejbActivate, ejbPas ssivate, ejb
bLoad, ejbSttore, setEnttityContextt, and
unsetEn ntityContextt.

The class
s must imple
ement thesee callback methods
m even
n if it doesn'tt use them, as is the cas
se for
most of these
t method
ds in the EJ
JB 2.1 example in Figuree 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.
Persiste
ent Fields and Properties
Let's now
w compare how
h persisten
nce is declarred for fieldss and properrties.

Figure
F 4: Comp
mparing Persistent Field and
d Property Decclarations

Persiste
ence declarations are
e simpler
In EJB 2.1
2 technolog gy, you spec
cify which fie
elds of the cllass need to be persistedd in a databbase
by defining public abbstract gette
er and setterr methods fo or those field
ds and by ma aking
specifications in a deeployment descriptor
d -- an approach h that many y programme ers find clum
msy
and far from
fr intuitive. EJB 3.0 technology
t does
d not requ uire these sp
pecificationss. In essence
e,
persisten
nce is built in
nto an entity
y. The persisstent state o
of an entity iis represente
ed either by its
persisten
nt fields or persistent
p pro
operties.

hat an entity is a POJO. Like a POJO


Recall th O, it can havve non abstrract, private instance
variables he AddressID
s, such as th D variable inn the Addresss class. In tthe Java Perrsistence AP PI, an
entity can have field--based or prroperty-baseed access. In n field-basedd access, thee persistence
e
provider accesses the state of the entity direectly through h its instancce variables. In property
y-
based ac ersistence prrovider uses JavaBeans--style get/se
ccess, the pe et accessor methods to
access th
he entity's pe
ersistent prooperties. All fields and pproperties inn the entity a
are persisted
d.
You can, however, ov verride a fielld or propertty's default p
persistence by marking it with
the @Traansient annotation or th he Java keyw word transie ent.
No XML
L descripto
or needed to
t declare persistentt fields
EJB 2.1 technology, entity bean fields are id dentified as p persistent fieelds in the b
bean's
deploymeent descriptoor, ejb-jar.x
xml, an oftenn large and ccomplex XM ML file. In adddition to cod
ding
public ac
ccessor meth hods in the entity bean class, you m must specifyy in the deplooyment
or a cmp-fie
descripto eld element for
f each pers sistent field.. In the Java
a Persistence e API, you nno
longer ne
eed to providde a deploymment descrip ptor, called a an XML desccriptor in the e Java
Persisten
nce API, to sp
pecify an enntity's persisttent fields.

Default mappings
s are used where
w poss
sible
In EJB 2.1
2 technolog gy, you defin
ne the mapp ping between bean's fields and their
n an entity b
corresponding datab base columns in a vendo or-specific deeployment ddescriptor, suuch as sun-ejb-
jar.xml. By contrast, the Java Persistence API A does not require XML L descriptorrs. Instead, y
you
he mappings
specify th s in the entity class by marking
m the appropriatee persistent field or propperty
accessor method with the @Colu umn annota ation. You ca an, however,, take advan ntage of
annotatioon defaults. If you don'tt specify an @Column
@ a
annotation fo
for a specific
c persistent ffield
or properrty, a defaullt mapping to a database e column off the same na ame as the ffield or prop
perty
name is assumed.
a Allthough youu don't need to specify X ML descripttors, you hav ve the option
n of
using theem as an altternative to annotations
a or to suppleement anno otations. Using an XML
descriptoor might be useful
u in extternalizing object-relatio
o onal mappin ng informatio on. Also,
multiple XML descrip ptors can bee useful in ta
ailoring objeect-relationa
al mapping in nformation tto
different databases.
The Javaa Persistence e API standaardizes objecct-relational mapping, en nabling fullyy portable
applications.

Entity Identity
I
e also simpliifications in the way primary and co
There are omposite key
ys for entitie
es are speciffied.

Figure
e 5: Comparin
ng Settings forr Primary Key
ys
No XML
L descripto
or needed to
t specify the prima ry key
In EJB 2.1
2 technolog gy, the primaary key for an
a entity bea an -- that is, its unique identifier -- is
specified not in the entity
e bean class
c but ratther in its deeployment d descriptor. In
n the Java
Persistennce API, you don't need tot provide an n XML descrriptor to speecify an entity's primary y key.
Instead, you specify the primary y key in the entity
e class by marking an appropriiate persiste ent
field or persistent
p property with the @Id an nnotation. Yo ou can speccify compositte keys in tw wo
different ways, usingg an @IdClas ss annotatioon or an @Em mbeddedId annotation..

Relation
nships
So far, th
he focus has s been on the e coding sim mplifications that relate to basic persistence, tha
at is,
the persiistence of en heir fields orr properties. Now, let's lo
ntities and th ook at the co
oding
simplifica
ations that relate
r to entiity relationships. To do that, let's fo
ocus on
the CustomerBean classc and com mpare it to theCustomer
t rBean entity y. The CustoomerBean cllass
has a one-to-many unidirectiona
u al relationsh hip withAddrressBean an nd a many-m many
onal relation
bidirectio nship with SubscriptionB Bean. Let's ssee how much easier it is to specify
y an
equivalennt set of rela
ationships be etween the EJB
E 3.0 entiities.
Figure
e 6: Comparin ng Relationshipip Declaration
ns
Click here
e for a larger iimage
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
s are used for
f relation
nships whe
ere possiblle
You can take advanttage of defau ult mappings s to simplifyy the coding for relations
ship mappinng
even furtther. If you look
l at the create.sql
c file
e under the setup/sql diirectory for tthe Java
Persistennce Demo, yo ou will see a join table named
n CUST TOMER_ADD DRESS. Nottice that no
annotatioons are need ded in the Customer
entity to specify the mapping
m of the Customer and Addrress entities to the colum mns in the
CUSTOM MER_ADDRE ESS table. That's becaus se the table name and jo oin column names are tthe
defaults.

Inherita
ance and Polymorph
P ism
An imporrtant capabiility of the Jaava Persistence API is itts support fo
or inheritancce and
polymorp phism, some ething that was
w not avaiilable in EJB B 2.1. You caan map a hiierarchy of
entities, where
w one entity
e subclaasses anotheer, to a relatiional databa
ase structurre, and subm mit
queries against
a the base
b class. The
T queries area treated p polymorphiccally againstt the entire
hierarchy y.
The codee in the EJB 3.0 columnn below show ws an examp ple of the sup
pport for inh
heritance annd
polymorpphism. This sample is not taken from m the appliccation code b
because the e Java
Persisten
nce Demo do oes not use this
t feature. Here, ValueedCustomerr is an entityy that extend
ds
the Customerentity. The hierarchy is mappe ed to the CU
UST table:

Figure 7:
7 Support for Inheritance
I an
nd Polymorph
hism
Annotattions specify inherittance
The @Inh heritance an nnotation iddentifies a mapping
m stra
ategy for an eentity class hierarchy. Inn
this exammple, the strrategy speciffied by the value of the sstrategy elem ment is SING GLE_TABLE E.
This mea ans that the base class Customer
C and
a its subcllass ValuedC Customer a are mapped tto a
single tab
ble. By the way,
w you cann also speciffy a strategyy that joins tthe base clas ss and its
subclasses or that maps
m them too separate ta ables. A singgle table stra
ategy require es a
discriminnator column n in the tablle to distingu
uish betweeen rows in th he table for tthe base clas
ss
and rows s for the sub
bclasses. The e @DiscrimiinatorColum mn annotatiion identifies s the
discriminnator column ase, DISC. Th
n, in this ca he discrimin natorType eelement specifies that th he
discriminnator colum mn contains strings. The e @Discrimin natorValue annotation n is used to
specify th
he value of the
t discrimin nator column for the asssociated enttity.
Here, ValuedCustom mer instance es are distinguished from m other Cusstomer insta ances by hav ving
o VCUSTOM
a value of MER in the discriminato
d r column.

Defaults
s can be us
sed for varrious inherritance spe
ecification
ns
As is the case in manny other parrts of EJB 3..0 technolog gy and the Ja ava Persiste
ence API, you u can
rely on defaults
d to fu F example,, SINGLE_TA
urther simpliify coding. For ABLE is the default
inheritan
nce strategy,, so the code e sample doe es not need to specify it. In fact, youu don't need d to
he @Inheritance annota
specify th ation if you'rre using sing heritance. Th
gle-table inh he default fo
or
the discrriminatorTy ype element in the
@DiscriminatorCollumn annota ation is STRRING, so thee specificatio de sample is not
on in the cod
necessarry there eitheer. Also, for string discriiminator collumns, you d don't need tto specify a
discriminnator value. The default is the entity y name.

Entities
s can inherrit from otther entitie
es and from
m non-enttities
The EJB 3.0 example e illustrates inheritance
e from an enntity. Howeveer inheritancce from POJ
JOs
that are not
n entities -- for behavior and map pping attribu
utes -- is also allowed. T
The base enttity or
nonentityy can either be abstract or concrete.

Operatiions on Entities
Another pronounced d simplificatiion in the Ja
ava Persisten
nce API is th
he way entity
y operationss are
ed. For exam
performe mple, look at the way a subscription is removed in the editC Customer.jsp p file
and the EJB
E 2.1 Cus
stomerBean compared to the way th his is done in
n the busine
ess interface
e for
the EJB 3.0 session bean, Custo omerSession n.
Figu
ure 8: Comparring Operation
ns on Entities

Entity operations
o s are perforrmed direc
ctly on the
e entity
In EJB 2.1
2 technolog gy, a client must
m use the
e Java Namiing and Direectory Interfa face (JNDI) to
o
lookup thhe bean. In doing
d this, JNDI
J acquirees an object that represents the bea an's home
interface. In responsse, the EJB container
c creeates an insstance of thee bean and initializes its
s
he client can then call methods
state. Th m on th
he JNDI-acq quired objectt to perform operations on
the beann. In the EJBB 2.1 technology code sa ample above , JNDI is used to acquirre an object that
represents the LocallSubscriptio onHome interface. In th he removeSu ubscription n() business
method ofo the Custo omerBean, the findByPrrimaryKey()) method fin nds the
pertinentt SubscriptiionBean ins stance and reemoves the reference to o it. This rela
ationship uppdate
is synchrronized to thhe database when the trransaction in n which thiss CustomerB Bean's busin ness
method takes
t part co
ommits. Man ny developerrs view this process as nneedlessly inndirect and
complex..

By comparison, the Java


J Persisttence API req
quires no JNNDI-based lo ookup. An EntityManag ger
instance is used to fiind the pertiinent Customer and Su ubscription entities. The e reference tto
the Subs
scription
instance is then rem
moved from th he Custome er's subscrip
ption list. Alsso, the referrence to
the Custtomer instannce is remov ved from the Subscriptio on's custom mer list -- jusst as with
POJOs.
An entity manage
er manages
s the entitties
An EntittyManager instance
i is used
u to manage the statee and life cyycle of entitie
es within a
persistennce context. The entity manager
m is responsible
r ffor creating and removin ng persisten
nt
entity ins
stances and finding entiities by the entity's
e prim
mary key. It a
also allows q queries to be
e run
on entitie
es.

Depend
dencies can
n be injected
As illustrrated in the EJB 3.0 technology cod de example inn Figure 8, J
JNDI is no longer requirred
to get refferences to resources
r an
nd other objeects in an en
nterprise beaan's contextt. Instead, yo
ou
can use resource
r andd environmeent referencee annotation
ns in the bea
an class. The ese annotatiions
inject a resource
r on which the en
nterprise beean has a deependency. I n the EJB 33.0 technolog gy
code sammple, the @P PersistenceCContext annotation injeects an EntiityManagerr with a
transactiional persisttence contex
xt, on which the session bean has a dependency y. The contaainer
then take es care of ob
btaining the reference to
o the neededd resource annd providingg it to the be
ean.
Dependency injection n can dramaatically simp
plify what yo
ou have to coode to obtainn resource aand
environmmental refere ences.

Transac
ctions
Transacttion-related specification
ns are also simplified.
s

Figure 9: Comparing
C Tra
ansaction-Rellated Specifica
ations
No XML
L descripto
or needed to
t specify transactio
on attributtes
In EJB 2.1
2 technolog gy, you spec cify the trans
saction attrib butes for co
ontainer-man naged
transactiions in an offten lengthy and comple ex deployme nt descripto or. In EJB 3..0 technolog gy, an
XML descriptor is no ot needed to specify tran nsaction attrributes. Insttead, you cann use
the @Tra ansactionMa anagement annotation to specify co ontainer-maanaged trans sactions, as well
as to spe
ecify bean-mmanaged tran nsactions, annd the @Tra ansactionAtttribute ann notation to
specify trransaction attributes.
a In
n the EJB 3..0 technolog gy code samp ple, the
@Transa actionManag gement ann notation spec cifies contaiiner-manageed transactio ons for the
session bean.
b Because containerr-managed transactions
t fault type of transaction
s are the defa
demarcation, the ann n necessarry here. The @TransactiionAttributte annotation
notation is not n on
the remo ove() methodd specifies a transaction n attribute o f REQUIRED D, which is tthe default
transactiion type. So this annotaation is not necessary
n eitther. You woould need thhe annotatioon,
however,, to specify another
a tran
nsaction type e, such as "MMandatory" o or "Supportss".

Contain
ner-manage
ed entity managers
m are
a Java T
Transaction
n API entitty managers
In the Ja
ava Persistennce API, trannsactions invvolving EntiityManager operations can be
controlled in two way ys, either th
hrough JTA or
o by the app plication thrrough the
EntityTrransaction API.
A An entitty manager whose transsactions are controlled tthrough JTA A is
called a JTA
J entity manager.
m An entity manaager whose ttransactionss are controllled by
the EntittyTransactiion API is ca alled a resou
urce-local en
ntity manageer. A containner-managed d
entity maanager mustt be a JTA en ntity managger. JTA entiity manager transaction ns are started
d
and ende ed outside off the entity manager,
m an
nd the entity
y manager m methods sharre the
transactiion context of
o the sessio on bean meth hods that in
nvoke them.

Queries
s
Support for queries has
h been sig gnificantly en
nhanced in the Java Perrsistence AP
PI. Some of tthese
ments are sh
enhancem hown in Figu
ure 10.
Figu
ure 10: Compa
aring Query Sp
Specifications

No XML
L descripto
or needed to
t specify queries
In EJB 2.1
2 technolog gy, you defin
ne a query foor an entity bbean using Enterprise J JavaBeans q query
languagee (EJB QL). YouY specify the
t query in n the deploym ment descrip ptor for the b
bean, and
associatee it there witth a finder or select method for the b bean. In thee Java Persis stence API, yyou
can defin
ne a named -- - or static -- query in th
he bean classs itself. Youu also have tthe option off
creating dynamic qu ueries. To creeate a named d query, youu first definee the named query using g
the @Nam medQuery annotation.
a Then
T you crreate the preeviously-defiined query u using
the creatteNamedQu uery method d of the EntityManager.. In the EJB 3.0 technollogy example e,
two named queries area defined in n the Custoomer entity cclass:
findCusttomerByFirstName and d findCustomerByLastN Name. The n named queries are creatted
in the session bean, CustomerS Session, whiich provides the client code for the e entity. To create
a dynamic query, you u use the crreateQuery method of th he EntityManager. The e Java
nce API provides a Java Persistence query langu
Persisten uage that exttends EJB Q QL. You can use
Java Persistence que ery language e or native SQL
S in nameed or dynamic queries.
Support for dynamiic queries anda named queries
q is a
added
The Javaa Persistence
e API providees a Query API
A to createe dynamic qu ueries and n
named queriies.
mple, the Cus
For exam stomerSess sion class usses the Querry API on th he entity man
nager to crea
ate
the nameed queries fiindCustome erByFirstNa ame and fin ndCustomerrByLastNam me. The Querry
method setParamete
s er binds an argument to o a named p parameter. (BBy the way, support for
named parameters is s also a new
w feature in the
t Java Perrsistence APII: both name ed queries a
and
dynamic queries cann use named d parameters s as well as ppositional pa
arameters, a
although a ssingle
query cannot mix bo oth types of parameters.
p ) For examp ple, the setPa
arameter meethod in
findCusttomerByFirstName bin nds the firstn
name argum ment to the nnamed
parameteer :firstNam
mein the nam med query de he getResulttList method
efinition. Th d returns th
he
query res
sults.

All querries that use the Jav


va Persistence API arre polymorrphic
This mea
ans that whe
en a class is queried, alll subclasses that meet tthe query criiteria are als
so
returned.

The Jav
va Persiste
ence Query
y Language
e is an enh
hanced que
ery languag
ge
EJB QL has
h been a very
v popularr facet of EJB
B technologygy. However, despite its ppopularity, E
EJB
QL has laacked some of the features of a full structured q query languuage, such as s bulk updaate
and delette operations, outer join
n operations,, projection, and subqueeries. The Ja ava Persistence
query lannguage adds s those featu
ures. It also adds
a supporrt for outer jjoin-based p
prefetching. T
The
full range
e of the Java
a Persistence query lang guage can bee used in sta atic or dynamic queries.
However the Java Pe ersistence Deemo does no ot use the Jaava Persistennce query la
anguage
enhancem ments.

Testing
g Entities Outside
O of the Conta
ainer
Although h this can't be
b demonstrrated in a sid de-by side co ode compariison, testingg entities outtside
an EJB container
c is now much easier.
e Previously, the enntity bean ccomponent m model -- withh its
requiremments for hom me and component interrfaces, abstrract entity b bean classes,, and virtuall
persistennt fields -- made
m it difficu
ult to test enntity beans o outside of th
he containerr. The Java
Persistennce API remo oves the requ uirement forr these interrfaces. The o only thing re
equired for a
an
entity bean is a conc crete entity bean
b class --- a POJO -- that has perrsistent field
ds or persisttent
propertiees. In additioon, an entity y's life cycle is controlled
d through th he entity manager, not
through a home interface whose e life-cycle methods
m are iimplemented d by the EJB
B container..
Because all of this makes
m entitiees less depen ndent on inttervention by y the EJB co
ontainer, the e
entities can
c be more easily tested d outside off the contain ner.

ary
Summa
The aim of the new Java
J Persiste
ence API is to
t simplify thhe developm ment of persiistent entitie
es. It
meets this objective through a siimple POJO-based pers istence mod del, which re
educes the
number ofo required classes
c and interfaces. You
Y model y your data ussing POJOs, and then
annotatee them to tell the containner about an n entity's chaaracteristicss and the res
sources it neeeds.
You also use annotations for objject-relational mappingss and entity relationship ps, as well as
deploy-time instructiions. This annnotation-ba ased approa ach removes the need fo or often long and
complex,, XML-based d descriptorss. In many cases,
c the an
nnotations' d defaults are enough. You u
code specific attributtes of the an
nnotations only when th he defaults a are inadequaate.
Beyond these
t simpliffications, the Java Persiistence API a
adds capabiilities that w
were not in E
EJB
2.1 technnology, givin
ng you additiional power and flexibiliity in develop
ping and ussing persistent
entities. You can takke advantage e of query language enha ancements a and new feaatures such aas
inheritannce and polyymorphism to t perform more
m powerfu
ul and encom mpassing quueries. You ccan
exercise more contro ol over querie optimizations specific to your needs. In
es, and perfform query o
short, ussing the Java
a Persistence API is mucch simpler a and more inttuitive than it's
predecessors, yet it offers
o a more
e robust APII for creating
g, managingg, and using persistent
entities.
This articcle only high
hlights the simplification
s ns and enha ancements thhat the Javaa Persistencee API
offers. Yo
ou'll find moore extensive e information
n about the API, as well as other sim
mplificationss
made in EJB 3.0 technology, by examining the t Enterpriise JavaBean ns 3.0 Speciification. No
ow is
a good timme to try ouut EJB 3.0 te echnology annd the Java Persistencee API. See the Try It Out! box
at the beeginning of thhis article fo
or some goodd places to sstart.
What Ha appens to th he Old Entitty Model?

The old entity


e model is still going
g to remain a part of EJJB, and it alw
ways will bee a part of EJ
JB,
for comp
patibility reas
sons. The Ex xpert Groupp is currentlyy looking at a number o of the new
features in EJB 3.0, which would potentially y be useful ffor people ussing the old programmin ng
model, annd thinking about makiing those ava ailable for p
people using the older prrogramming
model. EJB
E 3.0 plan
ns to extend the EJB-QL L for the EJB B 2.1-style C
CMP entity beans. So if y you
want to stick
s o programming model for a while, you will be able to do that and stilll use
to the old
some of the
t new func ctionality.

Conclusiion

EJB 3.0 goes a long way toward making the EJB progra amming expeerience a pleeasant one bby
ng developm
simplifyin ment, facilita
ating test-driiven develop
pment, and ffocusing morre on plain JJava
objects (P
POJOs) rath her than on complex
c APIIs. One of th
he importantt aspects tha
at we have nnot
covered in
i detail in this
t article is
s the new peersistence fra
amework deefined in the specificatio
on.
For detaiils, check th
he EJB 3.0 API
A specificattion, and do ownload the EJB 3.0 perrsistence
documen ntation.

BEA Systtems is work


king actively
y on its EJB3
3 implementtation strateegy in BEA WWebLogic Se erver.
Details on
o the implem
mentation and
a the timelline will be p
provided on this Web sitte when they
y are
finalized..
Entitty Life Cyc
cle


This figure shows the life cycle of 0 entity. Theere are five sstates: does not exist, n
o an EJB 3.0 new,
managed d, detached
d, and remov ved.

he does not exist state to the new sstate, the folllowing occu
To transiition from th urs: plain old
d
Java obje
ect construc ction occurs such as Objject obj = neew Object().

To transiition from th he new state


e to the man
naged state, the followin
ng occurs: En
ntityManageer
method persist
p is inv
voked with the new obje
ect as argum
ment, the enttity method annotated a
as
PrePersis
st (if any) is invoked, the
e database in
nsert completes, the enttity method annotated a
as
PostPersiist (if any) is
s invoked.

he managed state to the


To transiition from th e detached sstate, the folllowing occu
urs: the entitty is
d to another tier.
serialized

To transiition from de
etached bac
ck to manag ged, the follo
owing occurss: the entity is de-serialiized,
the EntittyManager method
m mergge is invoked
d with the enntity object a
as argumentt.

While in the manage ed state, within a transaactional con ntext, you ccan execute an update q
query
on the enntity or use the
t entity pu ublic API: whhen the tran nsaction commmits, the fo
ollowing occu
urs:
the entity
y method an nnotated as PreUpdate (if any) is invvoked, the d database upd date comple
etes,
the entity
y method an nnotated as PostUpdate e (if any) is in
nvoked.

Also whille in the ma


anaged statee, within a trransactiona al context, tto refresh th
he entity, the
e
following
g occurs: EnttityManagerr method refrfresh is invokked with thee entity object as argumment,
the datab
base fetch coompletes, an
nd the entityy method an nnotated as P PostLoad (iff any) is then
n
invoked.











A persisttence unit is
i a logical grouping
g of the
t following
g:

x Entity
E manag ger: includinng, entity ma
anager proviider, the enttity managerrs obtained ffrom
itt, and entity manager co onfiguration..
x Data
D source (see
( "Specify
ying a Data Source
S in a Persistence Unit").
x Vendor
V exten
nsions (see "CConfiguring Vendor Exteensions in a Persistence e Unit").
x Persistent ma anaged class ses: the clas
sses you inteend to mana age using an
n entity mana ager,
namely, entitty classes, em mbeddable classes,
c andd mapped su uperclasses ((see "What
Persistent Ma anaged Classes Does Th his Persistennce Unit Inclu
ude?").

All
A persistentt managed classes in a given
g persisttence unit m
must be collo
ocated in the
eir
mapping
m to a single database.

x Mapping
M mettadata: the in
nformation that
t describ es how to mmap persistennt managed
cllasses to dattabase table
es. You can specify
s mapp ping metadaata using an
nnotations on
n
persistent ma anaged class ses and orm
m.xml files (seee "What is the orm.xmll File?").

Configu
uring a Life
e Cycle Calllback Metthod on an
n EJB 3.0 E
Entity

Using Annnotations
You can specify an EJB
E 3.0 entitty class metthod as a lifee cycle callba
ack method using any o
of the
following
g annotations:
x @PrePersist
@
x @PostPersist
@
x @PreRemove
@
x @PostRemove
@ e
x @PreUpdate
@
x @PostUpdate
@
x @PostLoad
@
Configuring a Life Cycle Callback Listener Method on an Entity Listener Class of
an EJB 3.0 Entity

Using Annotations
You can specify an EJB 3.0 entity listener method as a life cycle callback method using any of
the following annotations:
x @PrePersist
x @PostPersist
x @PreRemove
x @PostRemove
x @PreUpdate
x @PostUpdate
x @PostLoad
Configuring Inheritance for an EJB 3.0 Entity
Implementing EJB 3.0 Queries
{
Implementing an EJB 3.0 Named Query
Implementing an EJB 3.0 Dynamic Query
Configuring TopLink JPA Query Hints in an EJB 3.0 Query
}

Simplifying Persistence using JPA

Sridhar Reddy
Technology Evangelist
Sun Microsystems, Inc.
1

Goal of the Talk

Learn about the enhancements made in Java to simplify Persistence


The Java Persistence API was developed by the EJB 3.0 (JSR 220)
We will take an in-depth look at the Java Persistence API (JPA)

2
Agenda
• Java Persistence Requirements
• JPA Programming Model
• Persistence Context & Entity Manager
• Transaction
• O/R Mapping
• Entity Relationships
• Entity Inheritance Strategy
• Demo: Java Persistence using NetBeans IDE 5.5
• Entity Listeners

Java Persistence Requirements


• Simplification of the persistence model
> Elimination of deployment descriptor
• Light-weight persistence model
> In terms of programming and deployment
model as well as runtime performance
• Testability outside of the containers
> Create test clients that would use entities in a
non-managed environment
• Domain modelling through inheritance and
polymorphism
• Object/Relational (O/R) mapping
• Extensive querying capabilities 4
Common Java Persistence Between
J2SE and J2EE Environments

• Persistence API expanded to include use


outside of EJB container
• Evolved into “common” Java persistence API
> You can use new Java persistence API in Java SE,
Web, and EJB applications
• Support for pluggable, third-party
persistence providers
> Through persistence.xml

What is an Entity?
• Plain Old Java Object (POJO)
> Created by means of new keyword
• No required interfaces
• Has a persistence identity
• May have both persistent and non-persistent state
> Simple types (e.g., primitives, wrappers, enums)
> Composite dependent object types (e.g., Address)
> Non-persistent state (transient or @Transient)
• Can extend other entity and non-entity classes
• Serializable; usable as detached objects in other
tiers
> No need for data transfer objects
6
Entity Example
@Entity
public class Customer implements Serializable {
@Id protected Long id;
protected String name;
@Embedded protected Address address;
protected PreferredStatus status;
@Transient protected int orderCount;
public Customer() {}
public Long getId() {return id;}
protected void setId(Long id) {this.id = id;}

public String getName() {return name;}


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

}

Entity Identity
• Every entity has a persistence identity
> Maps to primary key in database
• Can correspond to simple type
> @Id—single field/property in entity class
> @GeneratedValue—value can be generated
automatically using various strategies (SEQUENCE,
TABLE, IDENTITY, AUTO)
• Can correspond to user-defined class
> @EmbeddedId—single field/property in entity class
> @IdClass—corresponds to multiple Id fields in entity
class
• Must be defined on root of entity hierarchy
or mapped superclass
8
Agenda
• Java Persistence Requirements
• JPA Programming Model
• Persistence Context & Entity Manager
• Transaction
• O/R Mapping
• Entity Relationships
• Entity Inheritance Strategy
• Demo: Java Persistence using NetBeans IDE 5.5
• Entity Listeners

Java Persistence Programming Model


• Entity is a POJO (no need to implement
EntityBean)
• Use of Annotation to denote a POJO as an entity
(instead of deployment descriptor)
// @Entity is an annotation
// It annotates Employee POJO class to be Entity
@Entity
public class Employee {
// Persistent/transient fields
// Property accessor methods
// Persistence logic methods
}
10
Persistence Entity Example
@Entity
Annotated as “Entity”
public class Customer {
private Long id;
private String name;
private Address address;
private Collection<Order> orders = new HashSet();
public Customer() {}
@Id denotes primary key
@Id public Long getID() {
return id; Getters/setters to access
} state
protected void setID (Long id) {
this.id = id;
}
11

Persistence Entity Example (Contd.)


...
// Relationship between Customer and Orders
@OneToMany
public Collection<Order> getOrders() {
return orders;
}
public void setOrders(Collection<Order> orders) {
this.orders = orders;
}
// Other business methods
...
}
12
Client View: From Stateless Session Bean
@Stateless
public class OrderEntry {
// Dependency injection of Entity Manager for
// the given persistence unit
@PersistenceContext
EntityManager em;
public void enterOrder(int custID, Order newOrder){
// Use find method to locate customer entity
Customer c = em.find(Customer.class, custID);
// Add a new order to the Orders
c.getOrders().add(newOrder);
newOrder.setCustomer(c);
}
// other business methods
}
13

Client Code: From Java SE Client

public static void main(String[] args) {


EntityManagerFactory emf =
Persistence.createEntityManagerFactory("EmployeeService");
EntityManager em = emf.createEntityManager();

Collection emps = em.createQuery("SELECT e FROM Employee e")


.getResultList();

// More code

14
Demo:
Creating Entities from Existing
Database Tables

www.netbeans.org/kb/docs/java/compile-on-save-screencast.html

15

Agenda
• Java Persistence Requirements
• JPA Programming Model
• Persistence Context & Entity Manager
• Transaction
• O/R Mapping
• Entity Relationships
• Entity Inheritance Strategy
• Demo: Java Persistence using NetBeans IDE 5.5
• Entity Listeners

16
Persistence Context & Entity Manager
• Persistence context
> Represents a set of managed entity instances at
runtime
> “Entity instance is in managed state”means it is
contained in a persistent context
> Inclusion or exclusion of an entity into/from the
persistence context will determine the outcome of
any persistence operation on it
> Not directly accessible to application, it is accessed
indirectly through entity manager – type of entity
manager determines how a persistence context is
created and removed
• Entity manager
> Performs life-cycle operations on entities – manages
persistence context 17

EntityManager
• Similar in functionality to Hibernate Session,
JDO PersistenceManager, etc.
• Controls life-cycle of entities
> persist() - insert an entity into the DB
> remove() - remove an entity from the DB
> merge() - synchronize the state of detached entities
> refresh() - reloads state from the database

18
Persist Operation

public Order createNewOrder(Customer customer) {


Order order = new Order(customer);

// Transitions new instances to managed. On the


// next flush or commit, the newly persisted
// instances will be inserted into the datastore.
entityManager.persist(order);

return order;
} 19

Find and Remove Operations


public void removeOrder(Long orderId) {
Order order =
entityManager.find(Order.class, orderId);

// The instances will be deleted from the


datastore
// on the next flush or commit. Accessing a
// removed entity has undefined results.
entityManager.remove(order);
}
20
Merge Operation

public OrderLine updateOrderLine(OrderLine


orderLine) {
// The merge method returns a managed copy of
// the given detached entity. Changes made to
the
// persistent state of the detached entity are
// applied to this managed instance.
return entityManager.merge(orderLine);
}
21

Agenda
• Java Persistence Requirements
• JPA Programming Model
• Persistence Context & Entity Manager
• Transactions
• O/R Mapping
• Entity Relationships
• Entity Inheritance Strategy
• Demo: Java Persistence using NetBeans IDE
• Entity Listeners

22
Transaction Types
• Two different transaction types
> Resource-local transactions
> JTA (Java Transaction API)
 Multiple participating resources
 Distributed XA transactions
• Transaction type is defined in persistence unit
(persistence.xml file)
> Default to JTA in a JavaEE environment and to
RESOURCE_LOCAL in a JavaSE environment
• Container managed entity manager use JTA
transactions
> Propagation of persistence context with a JTA
transaction is supported by the container – sharing
same persistence context among multiple entity 23
managers

@TransactionAttribute Annotation
• TransactionAttributeType.REQUIRED
• TransactionAttributeType.REQUIRES_NEW
• TransactionAttributeType.MANDATORY
• TransactionAttributeType.NOT_SUPPORTED
• TransactionAttributeType.NEVER
• TransactionAttributeType.SUPPORTS

24
Transactions & Persistence Context
• Transactions define when new, modified, or
removed entities are synchronized with the
database
• How persistence context is created and used is
determined by Transaction type (Resource-local
or JTA) and Transaction attribute (REQUIRED or
..)

25

Transaction & Persistence Context Example


@Stateless
public class AuditServiceBean implements AuditService {
@PersistenceContext(unitName="EmployeeService")
private EntityManager em;
@TransactionAttribute(TransactionAttributeType.REQUIRED) //Default
public void logTransaction(int empId, String action) {
// verify employee number is valid
if (em.find(Employee.class, empId) == null) {
throw new IllegalArgumentException("Unknown employee id"); }
LogRecord lr = new LogRecord(empId, action);
em.persist(lr);
}
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void logTransaction2(int empId, String action) {
logTransaction(empId, action);
} 26
Transactions & Persistence Context Example
@Stateless
public class EmployeeServiceBean implements EmployeeService {
@PersistenceContext(unitName="EmployeeService")
private EntityManager em;
@EJB
AuditService audit;
public void createEmployee(Employee emp) {
em.persist(emp);
audit.logTransaction(emp.getId(), "created employee");
}
public void createEmployee2(Employee emp) {
em.persist(emp);
audit.logTransaction2(emp.getId(), "created employee");
} 27

Agenda
• Java Persistence Requirements
• JPA Programming Model
• Persistence Context & Entity Manager
• Transaction
• O/R Mapping
• Entity Relationships
• Entity Inheritance Strategy
• Demo: Java Persistence using NetBeans IDE 5.5
• Entity Listeners

28
Object/Relational Mapping
• Comprehensive set of annotations defined for
mapping
> Relationships
> Joins
> Database tables and columns
> Database sequence generators
> Much more
• Specified using
> Annotations within the code
> Separate mapping file

29

Object/Relational Mapping

Logical and physical mapping views

Logical—object model (e.g., @OneToMany)

Physical—DB tables and columns (e.g., @Table)
 Support for basic, serialized objects and LOBs
 Unary, n-ary relationship mappings
 Rules for defaulting of DB table and
column names

Access to object state using fields or properties

Multiple tables, composite relationship keys
30
Simple Mappings
 Direct mappings of fields to columns
 @Basic—known field type maps to standard
DB column type
 @Lob—field typically maps to BLOB or CLOB
DB column type
 Used in conjunction with @Column
(physical mapping annotation)
 Defaults to the type deemed most appropriate
if no mapping annotation is present
 Can override any of the defaults
31

Simple Mappings
CUSTOMER
ID NAME C_RATING PHOTO

@Entity(access=FIELD)
public class Customer {
@Id
int id;

String name;

int c_rating;
@Lob
Image photo;
}

32
Simple Mappings
CUSTOMER
ID NAME CREDIT PHOTO

@Entity(access=FIELD)
public class Customer {
@Id
int id;

String name;
@Column(name=“CREDIT”)
int c_rating;
@Lob
Image photo;
}

33

Agenda
• Java Persistence Requirements
• JPA Programming Model
• Persistence Context & Entity Manager
• Transaction
• O/R Mapping
• Entity Relationships
• Entity Inheritance Strategy
• Demo: Java Persistence using NetBeans IDE 5.5
• Entity Listeners

34
Entity Relationships
• Model instance association between entities
• Supports unidirectional as well as bidirectional
relationships
> Unidirectional relationship: Entity A references B, but
B doesn't reference A
• Mapping defaults are specified for all bi-
directional as well as uni-directional cardinalities
• Cardinalities
> One to one
> One to many
> Many to one
> Many to many

35

Entity Relationships: Example


Many to many – Owning side

36
Entity Relationships: Example
Many to many – Inverse side

37

Entity Relationships and Cascading Behavior


• Cascading is used to propagate the effect of
an operation to associated entities
• Cascading operations will work only when
entities are associated to the persistence
context
> If a cascaded operation takes place on detached
entity, IllegalArgumentException is thrown
• Cascade=PERSIST
• Cascade=REMOVE
> Not advisable to use it on relationships other than one-
to-one and one-to-many relationships
• Cascade=MERGE Cascade=REFRESH
• Cascade=ALL 38
Agenda
• Java Persistence Requirements
• JPA Programming Model
• Persistence Context & Entity Manager
• Transaction
• O/R Mapping
• Entity Relationships
• Entity Inheritance Strategy
• Demo: Java Persistence using NetBeans IDE
• Entity Listeners

39

Entity Inheritance
• Entities can now have inheritance relationship
> They are POJO's
• Three inheritance mapping strategies (mapping entity
inheritance to database tables)
> Single table per class hierarchy
> Joined subclass
> Table per class
• Use annotation @Inheritance(..)

40
Entity Inheritance -Mapping Classes to Tables
• Use Java application metadata to specify mapping
Support for various inheritance mapping strategies
> SINGLE_TABLE [default]
 All the classes in a hierarchy are mapped to a single table
 Root table has a discriminator column whose value
identifies the specific subclass
> TABLE_PER_CLASS
 Each class in a hierarchy mapped to a separate table and
hence, all properties of the class
> JOINED
 The root of the hierarchy is represented by a single table
 Each subclass is represented by a separate table that
contains fields specific to the subclass as well as the
columns that represent its primary key(s)
41

Single Table Strategy


• All the classes in a hierarchy are mapped to a single
table
• Annotation to the parent Entity
> @Inheritance(strategy=InheritanceType.SINGLE_TABLE)
• Root table has a discriminator column whose value
identifies the specific subclass to which the instance
represented by row belongs
> @DiscriminatorColumn(columnDefinition="MYDTYPE")

42
Single Table Strategy Example
// Parent Entity
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
//default is SNGE_TABLE
public class Person implements Serializable {...}
private String name;

@Entity // Child Entity


public class Student extends Person {...}
private String school;
private double grade;

@Entity // Child Entity


public class Teacher extends Person {...}
43

Single Table Strategy Example

44
Joined Strategy
• The root of the hierarchy is represented by a single
table
• Each subclass is represented by a separate table that
contains fields specific to the subclass as well as the
columns that represent its primary key(s)
• Annotation to the parent Entity
> @Inheritance(strategy=InheritanceType.JOINED)

45

Joined Table Strategy Example


// Parent Entity
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
@DiscriminatorColumn(columnDefinition="MYDTYPE")
public class Person implements Serializable {...}
private String name;

// Child Entity
@Entity
public class Student extends Person {...}
private String school;
private double grade;

// Child Entity
@Entity
public class Teacher extends Person {...}

46
Demo:
Using different strategies for
Inheritance ans how database
tables are created:
SINGLE_TABLE
JOINED

47

Entity Inheritance Strategy


• SINGLE_TABLE [default]
> All the classes in a hierarchy are mapped to a single table
> This strategy provides good support polymorphic
relationships between entities and queries that cover the
entire class hierarchy
> May contain null fields for some subclass data
• TABLE_PER_CLASS
> Each class in a hierarchy mapped to a separate table and
hence, provides poor support for polymorphic relationships
> requires SQ union or separate SQL queries for each subclass
• JOINED
> no null fields => compact data
> This provides good support for polymorphic relationships, but
requires one or more join operations – may result in poor
performance 48
Embedded Objects

Embedded Objects
• @Embeddable used to mark an embeddable
object
• Embeddable object is stored as intrinsic part of
an owning entity
> Doesn't have its own identity
• Each persistent field/property of embeddable
object is mapped to the same database table
that represents the owning entity

50
Embedded Objects
@Entity
public class Customer {
@Id
int id; ID NAME CUSTOMER
@Embedded CREDIT PHOTO

CustomerInfo info;
}
public class CustomerInfo {
@Embeddable
String name;
int credit;

@Lob
Image photo;
}
51

Agenda
• Java Persistence Requirements
• JPA Programming Model
• Persistence Context & Entity Manager
• Transaction
• O/R Mapping
• Entity Relationships
• Entity Inheritance Strategy
• Demo: Java Persistence using NetBeans IDE
• Entity Listeners

52
Entity Listeners
• Listeners or callback methods are designated to
receive invocations from persistence provider at
various stages of entity lifecycle
• Callback methods
> Annotate callback handling methods right in the entity
class or put them in a separate listener class
> Annotations
 PrePersist / PostPersist
 PreRemove/ PostRemove
 PreUpdate / PostUpdate
 PostLoad

53

Entity Listeners: Example – 1

54
Entity Listeners: Example – 2

55

Entity Listeners: Example – 3

56
Summary,
Resources,
Sun Developer Network

Java Persistence Summary

• Simplifies persistence model


• Supports Light-weight persistence model
• Support both J2SE and J2EE
environments
• O/R mapping through annotation
• Extensive querying capabilities

58
Resources
http://developers.sun.com/events/techdays/presentations/

• Glassfish persistence homepage


> https://glassfish.dev.java.net/javaee5/persistence
• Persistence support page
> https://glassfish.dev.java.net/javaee5/persistence/entit
y-persistence-support.html
• Blog on using persistence in Web applications
> http://weblogs.java.net/blog/ss141213/archive/2005/12
/using_java_pers.html
• Blog on schema generation
> http://blogs.sun.com/roller/page/java2dbInGlassFish#a
utomatic_table_generation_feature_in
59

Sridhar Reddy
Technology Evangelist
Sun Microsystems, Inc

Sridhar.Reddy@sun.com

60
Java Persistene API:
Best Practices
Srinidhi Nirgunda
Architecture Solution Team

Agenda

Entities
Entity Manager
Persistence Context
Queries
Transaction

2
Objective
>Highlight and discuss about the best
practices for JPA
> Assumption – You already know JPA
> Not an introductory JPA session
• Discuss advance concepts

Very Brief Overview of JPA


>Introduced as part of JavaEE 5
• Simplified Persistence model
>POJO based programming model
•No interfaces, convention, annotation based
> Support rich domain modeling
•Inheritance and polymorphism
> Expanded query language
> Standardize object/relational mapping
> Usable in JavaEE and JavaSE
•Unified persistence model across the Java platform

4
Major Components of JPA

Why to follow Best Practices?

Portability
Features

Simplicity

6
Agenda

Entities
Entity Manager
Persistence Context
Queries
Transaction

Things to Remember About Entities


> Are not EntityBeans!!!
> Entities are POJOs
•No remote calls involved, methods are executed locally
•Methods can now be coarse or fine grained
> Entity states are New, Managed, Detached, Removed
•No remote or local concept
> Need to be aware when entities are detached
•Outside of transaction context
•Remember to merge

8
Primary Keys
> Annotated by @Id
> For simple @Id, can specify primary key generator
•TABLE – most portable
•SEQUENCE, IDENTITY
Uses the database's sequence and identity column


Not portable across database or persistence manager




•AUTO – pick the best strategy


> For portability, specify generator to give mapping
details
@TableGenerator(name=”mygen”, table=”ID_TABLE”
, pkColumnName=”GEN_KEY”, pkColumnValue=”EMP_ID”
, valueColumnName=”GEN_VALUE”)
@Id @GenerateValue(strategy=TABLE, generator=”mygen”)
long id;
GEN_KEY GEN_VALUE
ID_TABLE
EMP_ID Last generated
value 9

Example – Domain Model


@Entity public class Employee {
@Id private int id;
private String firstName;
private String lastName;
@ManyToOne(fetch=LAZY)
private Department dept;
...
}
@Entity public class Department {
@Id private int id;
private String name;
@OneToMany(mappedBy = "dept", fetch=LAZY)
private Collection<Employee> emps = new ...;
...
}

10
Maintaining Relationship
> Application bears the responsibility of maintaining
relationship between objects

Before After
Employee1 Employee1
Department A Department A
Employee2 Employee2
Inconsistent!

Department B Employee3 Department B Employee3

11

Example – Managing Relationship


INCORRECT
public int addNewEmployee(...) {
Employee e = new Employee(...);
Department d = new Department(1, ...);

e.setDepartment(d);
//Reverse relationship is not set
em.persist(e);
em.persist(d);

return d.getEmployees().size();
}

12
Example – Managing Relationship
CORRECT
public int addNewEmployee(...) {
Employee e = new Employee(...);
Department d = new Department(1, ...);

e.setDepartment(d);
d.getEmployees().add(e);
em.persist(e);
em.persist(d);

return d.getEmployees().size();
}

13

Navigating Relationships
> Data fetching strategy
•EAGER – immediate
•LAZY – load only when needed
> LAZY is good for large objects and/or with
relationships with deep hierarchies
> EAGER is automatic when query is performed outside
of a transaction
•Entities are also detached immediately
> Cascade specifies operations on relationships
•ALL, PERSIST, MERGE, REMOVE, REFRESH
•The default is do nothing
> Avoid MERGE with deep hierarchies
•If want to do it, limit the scope
14
Choosing Between EAGER And LAZY
> EAGER – too many joins?
SELECT d.id, ..., e.id, ...
FROM Department d left join fetch Employee e
on e.deptid = d.id

> LAZY – N + 1 problem


SELECT d.id, ... FROM Department d // 1 time
SELECT e.id, ... FROM Employee e
WHERE e.deptId = ? // N times

> Use a different query


•Return only employees that matches WHERE clause
•Benefits of EAGER and LAZY
SELECT d from Department d
LEFT JOIN FETCH d.employees
WHERE d.id = 1
15

Navigating Relationships
> Accessing a LAZY relationship from a detached entity
•May get an exception
•My get a null
•May get a previously cached value
> Use JOIN FETCH for such objects
•Fetch type is set to EAGER
•Access the collection before entity is detached – like a sync
//Forces all employees to be loaded
d.getEmployees().size();

16
Using Cascade
@Entity public class Employee {
@Id private int id; Employee
private String firstName;
private String lastName;
@ManyToOne(cascade=MERGE, fetch=LAZY) cascade=ALL
private Department dept;
... Department
}
@Entity public class Department { X
@Id private int id;
private String name; DepartmentCode
@OneToMany(mappedBy = "dept"
cascade=MERGE, fetch=LAZY)
private Collection<Employee> emps = new ...;
@OneToMany
private Collection<DepartmentCode> codes;
...
}

17

Mapping Inheritance Hierarchies

Employee
---------------------------
int id
String firstName
String lastName
Department dept

PartTimeEmployee FullTimeEmployee
------------------------ -----------------------
int rate double salary

18
Single Table Per Class
> Benefits
•Simple EMPLOYEE
---------------------------
•No joins required ID Int PK,
FIRSTNAME varchar(255),
> Drawbacks LASTNAME varchar(255),
DEPT_ID int FK,
•Not normalized RATE int NULL,
SALARY double NULL,
•Requires columns DISCRIM varchar(30)
corresponding to subclasses'
state to be null
•Table can have too many
columns

@Inheritance(strategy=SINGLE_TABLE)
19

Joined Subclass
> Benefits EMPLOYEE
•Normalized database ID int PK,
FIRSTNAME varchar(255),
•Database view same as LASTNAME varchar(255),
domain model DEPT_ID int FK,
DISCRIM varchar(30)
•Easy to evolve domain model
PARTTIMEEMPLOYEE
> Drawbacks
•Poor performance in deep ID int PK FK,
RATE int NULL
hierarchies
•Poor performance for
FULLTIMEEMPLOYEE
polymorphic queries and
relationships ID int PK FK,
SALARY double NULL

@Inheritance(strategy=JOINED)
20
Table Per Class
> Benefits EMPLOYEE

•No need for joins if only leaf ID int PK,


FIRSTNAME varchar(255),
classes are entities LASTNAME varchar(255),
DEPT_ID int FK
> Drawbacks
PARTTIMEEMPLOYEE
•Not normalized
ID int PK,
•Poor performance when FIRSTNAME varchar(255),
querying non-leaf entities-union LASTNAME varchar(255),
DEPT_ID int FK,
•Poor support for polymorphic RATE int NULL
relationships FULLTIMEEMPLOYEE

> This strategy is not ID int PK,


mandatory FIRSTNAME
LASTNAME
varchar(255),
varchar(255),
DEPT_ID int FK,
SALARY double NULL

@Inheritance(strategy=TABLE_PER_CLASS)
21

Agenda

Entities
Entity Manager
Persistence Context
Queries
Transaction

22
Container vs Application Managed
> Container managed entity managers
•Injected into application
•Automatically closed
•JTA transaction – propagated
> Application managed entity managers
• Used outside of the JavaEE 5 platform
• Need to be explicitly created
- Persistence.createEntityManagerFactory()
• RESOURCE_LOCAL transaction – not propagated
• Need to explicitly close entity manager

23

Threading Models and Injections


> Field injection is only supported for instance variable
• Not thread-safe
> Threading models for JPA components
• EntityManager is not thread-safe
• EntityManagerFactory is thread-safe
> Dangerous to inject non threadsafe objects into
stateless components
• Inconsistent data
• Data viewable to other threads
> Off topic – same goes for other JavaEE 5 components
• Eg. EJBs, web services, other resources

24
Beware of Injected EntityManagers
public class ShoppingCartServlet extends HttpServlet {
@PersistenceContext EntityManager em;
protected void doPost(HttpServlet req, ...) {
Order order order = ...;
em.persist(order);
} WRONG
public class ShoppingCartServlet extends HttpServlet {
@PersistenceUnit EntityManagerFactory factory;
protected void doPost(HttpServlet req, ...) {
EntityManager em = factory.createEntityManager();
Order order order = ...;
em.persist(order);
}
CORRECT
25

Agenda

Entities
Entity Manager
Persistence Context
Queries
Transaction

26
Persistence Context
> Two types of persistence context
> Transaction scoped
• Used in stateless components
• Typically begins/ends at request entry/exit points
respectively
> Extended scoped persistence context
• Used when business transaction spans multiple request
• Ideal place to create extended PC is at the beginning of a
business process or session
• Supported in StatefulSessionBean and application
managed EntityManager
> Persistence context acts as a cache for entities

27

Persistence Context and Caching


String empId = “12345”;
Employee employee = em.find(Employee.class, empId);
//Do something with it
. . .
Meanwhile empId 12345 have been changed

//Reload the employee


employee = em.find(Employee.class, empId);

Query query = em.createQuery(“SELECT e FROM Employee e “


+ “WHERE e.ID = :ID”).setParameter(“ID”, empId);
employee = (Employee)query.getSingleResult();

Will I get the new data for employee?


28
Persistence Context as Cache
> Answer: It depends
> Entities managed by persistence context
• Are not refresh until EntityManager.refresh() is
explicitly invoked
• Are not synchronized with database until
EntityManager.flush() is invoked either explicitly or
implicitly when persistence context is closed
> Entities remained managed by persistence context
until
• EntityManager.clear() is invoked
• Transaction commits

29

Concurrency - Optimistic vs Pessimistic


> Optimistic lock is the default
• Based on version consistency
• Suitable for application with few parallel updates
> Pessimistic lock for lots of parallel updates
• May result in lots of rollback – be prepare to handle them
• Not supported in JPA
• Need to resort to vendor specific extensions
• Eg. Glassfish/EclipseLink – eclipselink.pessimistic-
lock property

30
Preventing Stale Data and Parallel Updates
> JPA simplifies persistence but does not guard against
parallelism
> Introduce @Version for optimistic locking
• Used by persistence manager for performing versioning
• Can be int, Integer, short, Short, long, Long,
Timestamp
• Not used by the application
• Updated when transaction commits, merged or acquiring a
write lock
public class Employee {
@ID int id;
@Version Timestamp timestamp;
...

> Perform read or write locks on entities


31

Preventing Parallel Updates – 1


tx1.begin(); tx2.begin();
//Joe's employee id is 5 //Joe's employee id is 5
//e1.version == 1 //e1.version == 1
e1 = findPartTimeEmp(5); e1 = findPartTimeEmp(5);

e1.raiseByTwoDollar();

//Joe's current rate is $9


Time

if(e1.getRate() < 10)


tx1.commit(); e1.raiseByFiveDollar();
//e1.version == 2 in db

//e1.version == 1 in db?
tx2.commit();
//Joe's rate will be $14
//OptimisticLockException

32
Preventing Stale Data

tx1.begin(); tx2.begin();
d1 = findDepartment(dId);
e1 = findEmp(eId);
//d1's original name is d1 = e1.getDepartment();
//”Engrg” em.lock(d1, READ);
d1.setName(“MarketEngrg”); if(d1's name is “Engrg”)
e1.raiseByTenPercent();
tx1.commit();
Time

//Check d1.version in db
tx2.commit();
//e1 gets the raise he does
//not deserve
//Transaction rolls back

33

Preventing Parallel Updates – 2

tx1.begin(); tx2.begin();
e1 = findDepartment(dId);
e1 = findEmp(eId);
d1 = e1.getDepartment();
em.lock(d1, WRITE);
//version++ for d1
em.flush();
Time

//d1's original name is


//”Engrg” if(d1's name is “Engrg”)
d1.setName(“MarketEngrg”); e1.raiseByTenPercent();
tx1.commit();
//tx rolls back

tx2.commit();

34
Bulk Updates
> Update directly against the database
• By pass EntityManager
• @Version will not be updated
> Entities in persistence context may be outdated
tx.begin();
int id = 5; //Joe's employee id is 5
e1 = findPartTimeEmp(id); //Joe's current rate is $9
//Double every employee's salary
em.createQuery(
“Update Employee set rate = rate * 2”).executeUpdate();
//Joe's rate is still $9 in this persistence context
if(e1.getRate() < 10)
e1.raiseByFiveDollar();
tx.commit();
//Joe's salary will be $14

35

Agenda

Entities
Entity Manager
Persistence Context
Queries
Transaction

36
Query Types – 1
> Named query
• Like findByXXXX() from EntityBeans
• Compiled by persistence engine
• Created either with @NamedQuery or externalized in
orm.xml
> Dynamic query
• Created dynamically by passing a query string to
EntityManager

• Beware of SQL injection, better to use with named


parameters

37

Query Types – 1

Query query = em.createQuery(“select ...”);

q = em.createQuery(“select e from Employee e WHERE ”


+ “e.empId LIKE '” + id + “'”);

NOT GOOD

q = em.createQuery(“select e from Employee e WHERE ”


+ “e.empId LIKE ':id'”);
q.setParameter(“id”, id);

GOOD

38
Query Types – 2
> Native query
• Leverage the native database querying facilities
• Not portable – ties queries to database

39

Flush Mode
> Controls whether the state of managed entities are
synchronized before a query
> Types of flush mode
• AUTO – immediate, default
• COMMIT – flush only when a transaction commits
• NEVER – need to invoke EntityManger.flush() to
flush JTA transaction
//Assume
Order order = em.find(Order.class, orderNumber);
//Do something to order
em.persist(order);
Query q = em.createNamedQuery(“findAllOrders”);
q.setParameter(“id”, orderNumber);
q.setFlushMode(FlushModeType.COMMIT);
//Newly added order will NOT visible – not committed
List list = q.getResultList();

40
Agenda

Entities
Entity Manager
Persistence Context
Queries
Transaction

41

Transactions
> Do not perform expensive and unnecessary
operations that are not part of a transaction
• Hurt performance
• Eg. logging – disk write are expensive, resource contention
on log
> Do not use transaction when browsing data
• Create your own EntityManager as oppose to injected

42
JTA and RESOURCE_LOCALEntityManager
> Container managed EntityManger can be JTA or
RESOURCE_LOCAL
• JTA EntityManager  JTA transaction – container managed
• RESOURCE_LOCAl  non-JTA transaction
> RESOURCE_LOCAL EntityManagers are created
from
EntityManagerFactory.createEntityManager
()

43

Creating JTA Transactions


> Create EntityManger inside a JTA transaction
• Get an instance of JTA transaction from container or client
container (for JavaSE)
@Resource UserTransaction utx;
. . .
utx.begin();
EntityManager em = emf.createEntityManager();
//em is now JTA

> Join a JTA transaction


@Resource UserTransaction utx;
. . .
EntityManager em = emf.createEntityManager();
//em is is RESOURCE_LOCAL
utx.begin();
em.joinTransaction();

44
Vendor Specific Features - Portability
> Persistence properties - Compile-time and runtime
portability
• <property name=“toplink.logging.thread” value=“false”/>
• <property name="toplink.ddl-generation" value="create-
tables"/>
> Vendor Annotations – Compile time dependencies
• @Cache(disable-hits=TRUE) // TopLink annotation
• @DataCache(enabled=false) // OpenJPA annotation
> Customizations – pluggable dependencies
• public class MySessionCustomizer
implements SessionCustomizer {}
> All of these may and often will result in subtle runtime
dependencies
45

Summary
> No Spec can ever offer everything that you want
> JPA adds value and support for users
> Developers should be aware of non-portable
features, and consequences of using them
> Keep the application Simple, Portable and Flexible by
using best practices

46
Srinidhi Nirgunda

47
Java Persistence API:
Best Practices
Carol McDonald
Java Architect

Agenda

>Entity Manager
>Persistence Context
>Entities
>Schema & Queries
>Transaction

2
EntityManager set of entities managed by
API for managing entities Entity Manager

EntityManager
persist()
remove()
refresh()
merge()
find()
createQuery()
createNamedQuery() Persistence
contains() Context
flush()

Catalog Java EE Application

Registration Application
Managed Bean Entity
Class

Item
DB

ManagedBean Catalog
Session
JSF Components
Bean

4
EJB EntityManager Example
@Stateless
public class Catalog implements CatalogService {

@PersistenceContext(unitName=”PetCatalogPu”)
EntityManager em;

@TransactionAttribute(NOT_SUPPORTED)
public List<Item> getItems(int firstItem,
int batchSize) {
Query q = em.createQuery
("select i from Item as i");
q.setMaxResults(batchSize);
q.setFirstResult(firstItem);
List<Item> items= q.getResultList();
return items;
}
} 5

Catalog Spring JPA Application

Registration Application
Managed Bean Entity
Class

Item
DB

ItemController
Catalog
Spring
JSF Components
Bean
Spring
Framework

6
Spring with JPA
Component Stereotype
@Repository Spring transactions use aop
@Transactional
public class CatalogDAO implements CatalogService {
@PersistenceContext(unitName="PetCatalogPu")
private EntityManager em;

@Transactional(readOnly=true)
public List<Item> getItems(int firstItem,int batchSize) {
Query q =
em.createQuery("select object(o) from Item as o");
q.setMaxResults(batchSize);
q.setFirstResult(firstItem);
List<Item> items= q.getResultList();
return items;
}

Container vs Application Managed


Container managed entity managers (EJB, Spring Bean,
Seam component)
• Injected into application
• Automatically closed
• JTA transaction – propagated
Application managed entity managers
> Used outside of the JavaEE 5 platform
> Need to be explicitly created
 Persistence.createEntityManagerFactory()
> RESOURCE_LOCAL transaction – not propagated
> Need to explicitly close entity manager

8
Agenda

>Entity Manager
>Persistence Context
>Entities
>Queries
>Transaction

Persistence Context set of entities manag


• Persistence context acts Entity Manager
as a first level cache for
entities EntityManager
persist()
• Two types of
remove()
persistence context refresh()
> Transaction scoped merge()
> Extended scoped find()
persistence context createQuery()
createNamedQuery() Persistence
contains() Context
flush()

10
Level1 and Level2 caches
Persistence Context is a Level 1 cache

Transaction Transaction Transaction

Persistence Context Persistence Context Persistence Context


(EntityManager) (EntityManager) (EntityManager)

L2 Cache
(Shared Cache)

Entity managers for a specific PersistenceUnit on a given Java Virtual Machine (JVM™)

The terms “Java Virtual Machine” and “JVM” mean a Virtual Machine for the Java™ Platform. Source:http://weblogs.java.net/blog/guruwons/ar
11

Entity Lifecycle
new()
New Detached
Entity Entity
Updates PC ends
persist()
Persistence Context Merge()
Managed
find()
Managed Managed
Entity
Entity Entity

Guaranteed Scope of Transaction commit


Object Identity
only one manage entity
in PC represents a row
remove()
Removed
Entity
12
Entity Lifecycle Illustrated – The Code
@Stateless public ShoppingCartBean New entity
implements ShoppingCart {
Persisten
@PersistenceContext EntityManager entityManager;

public OrderLine createOrderLine(Product product


, Order order) {
OrderLine orderLine = new OrderLine(order, produ
entityManager.persist(orderLine);
return (orderLine); Managed entity
}

Detached entity
}

13

Scope of Identity
@Stateless public ShoppingCartBean implements ShoppingCart {

@PersistenceContext EntityManager entityManager; Persistence


public OrderLine createOrderLine(Product product,Order order)
OrderLine orderLine = new OrderLine(order, product
entityManager.persist(orderLine);
OrderLine orderLine2 =entityManager.find(OrderLine,
orderLine.getId()));
(orderLine == orderLine2) // TRUE
return (orderLine);
}
Multiple retrievals of the same object return referenc

}
14
Persistence Context
• Two types of persistence context
• Transaction scoped
> Used in stateless components
> Typically begins/ends at request entry/exit points
respectively
• Extended scoped persistence context

15

Persistence Context Propagation

@Stateless public class ShoppingCartBean implements


ShoppingCart {
@EJB InventoryService inv;
@EJB OrderService ord;

public void checkout(Item i, Product p) {


inv.createOrder(item);
ord.updateInventory(Product p)
} Persistence context
}

16
Persistence Context Propagation

@Stateless public class OrderServiceBean implements


OrderService {
@PersistenceContext EntityManager em1;
public void createOrder(Item item) {
em1.persist(new Order(item));
}
}
@Stateless public class InventoryServiceBean implements
InventoryService {
@PersistenceContext EntityManager em2;
public void updateInventory(Product p) {
Product product = em2.merge(p);
...
17

Declarative Transaction Management


Example

Check Out
New Persistence Persistence Context
Context Propagated
Shopping PC
1. Update Inventory PC
Cart Inventory Service
TX_REQUIRED TX_REQUIRED

Order PC
2. Create Order Service
Transaction
TX_REQUIRED
Attributes

18
AuditServiceBean

@Stateless
public class AuditServiceBean implements AuditService {
@PersistenceContext
private EntityManager em; NEW
PC !

@TransactionAttribute(REQUIRES_NEW)
public void logTransaction2(int id, String action) {
LogRecord lr = new LogRecord(id, action);
em.persist(lr);
}

19

Declarative Transaction Management


Example 2

Check Out
New Persistence Persistence Context
Context Propagated
Shopping PC
1. Update Inventory PC
Cart Inventory Service
REQUIRED REQUIRED

Audit PC2
2. log transaction Service
Transaction
REQUIRES_NEW
Attributes
NEW
PC !
20
Persistence Provider PC Transaction Features

• Attribute-level change tracking


• Only the minimal updates are sent to the database
• Orders INSERT, UPDATE and DELETE statements
• Minimizes database interactions
• EntityManager flush SQL prior to commit

21

Conversation with detached entity


Conversation

request response request response


transaction-scoped transaction-scoped
persistence context Detached
persistence context
Entity

Persistence Context Detached Persistence Context


Managed Managed Entity Managed Managed
Entity Managed Entity Entity Managed Entity
Entity Entity
merge()

22
Conversation with detached entity
@Stateless public ShoppingCartBean implements ShoppingCart {
@PersistenceContext EntityManager entityManager;

public OrderLine createOrderLine(Product product,Order order) {


OrderLine orderLine = new OrderLine(order, product);
entityManager.persist(orderLine); Managed entity
return (orderLine);
}
Detached entity
public OrderLine updateOrderLine(OrderLine orderLine)
OrderLine orderLine2 =entityManager.merge(orderLine));
return orderLine2;
}
Managed entity
}

23

Types of Persistence Context


• Persistence Context
> lifetime maybe transaction-scoped or extended
• Transaction-scoped persistence context
• Extended persistence context
> spans multiple transactions

24
Conversation with Exented Persistence Context
Conversation

request response request response


extended
persistence context

Persistence Context
Managed Managed Managed
Entity Entity Entity

25

Extended Persistence Context


@Stateful public class OrderMgr {
//Specify that we want an EXTENDED
@PersistenceContext(type=PersistenceContextType.EXTENDED
EntityManager em;
//Cached order
private Order order;
//create and cache order
public void createOrder(String itemId) {
//order remains managed for the lifetime of the bea
Order order = new Order(cust);
em.persist(order);
} Managed entity
public void addLineItem(OrderLineItem li){
order.lineItems.add(li);
}
Managed entity
26
Extended Persistence Context
@Stateful public class DeptMgr {
@PersistenceContext(type=PersistenceContextType.EXTENDED
EntityManager em;
private Department dept;

@TransactionAttribute(NOT_SUPPORTED)
public void getDepartment(int deptId) {
dept = em.find(Department.class,deptId);
}
@TransactionAttribute(NOT_SUPPORTED)
public void addEmployee(int empId){
emp = em.find(Employee.class,empId);
dept.getEmployees().add(emp);
emp.setDepartment(dept);
}
@Remove
@TransactionAttribute(REQUIRES_NEW)
public void endUpdate(int deptId) {
dept = em.find(Department.class,deptId);
}
27

Persistence Context-Transactional vs. Extended


@Stateless
public class OrderMgr implements OrderService {

@PersistenceContext EntityManager em;


public void addLineItem(OrderLineItem li){
look up the order
// First, look up the order.
Order order = em.find(Order.class, orderID);
order.lineItems.add(li);
}

@Stateful
public class OrderMgr implements OrderService {
@PersistenceContext(type = PersistenceContextType.EXTENDED))
EntityManager em;
// Order is cached
Managed entity
Order order
public void addLineItem(OrderLineItem li){
No em.find invoked
// No em.find invoked for the order object
order.lineItems.add(li);
}
28
Persistence Context Micro Benchmark
• Micro benchmark with lots of lookups
• Persistence context is caching entities
120%

100%

80%

tx/sec
60%

40%

20%

0%
Extended
Source: Internal benchmarks
29

SEAM Conversations
@Name("shopper")
@Scope(CONVERSATION)
public class BookingManager { SEAM injected

@In EntityManager entityManager;


private Booking booking;

@Begin public void selectHotel(Hotel selectedHotel){


hotel = em.merge(selectedHotel);
}
@End public void confirm() {
em.persist(booking);
SEAM conversation
}
}
30
Concurrency and Persistence Context

User 1 transaction User 2 transaction


Persistence Context 1 Persistence Context 2

same entity

Entity Manager Entity Manager

Object Identity
only one manage entity
in PC represents a row

Data source
31

Optimistic versus Pessimistic Concurrency


• Optimistic Concurrency
> Pros—No database locks held
> Cons—Requires a version attribute in schema
 user or app must refresh and retry failed updates
> Suitable when application has few parallel updates
• Pessimistic Concurrency
> Lock the row when data is read in
 database locks the row upon a select
 (SELECT . . . FOR UPDATE [NOWAIT])

> Pros—Simpler application code


> Cons—Database locks
 limits concurrent access to the data = scalability
 May cause deadlocks
 Not in JPA 1.0 (vendor specific), supported in JPA 2.0

> Suitable when application has many parallel updates 32


Preventing Parallel Updates
use @Version for optimistic locking
public class Employee { Can be int, Integer, short
@ID int id;
@Version int version;
...

Used by persistence manager , Results in following SQL


“UPDATE Employee SET ..., version = version + 1
WHERE id = ? AND version = readVersion”

Version Updated when transaction commits, merged or


acquiring a write lock
OptimisticLockException if mismatch
Not used by the application!

33

Preventing Parallel Updates – 1


tx1.begin(); tx2.begin();
//Joe's employee id is 5 //Joe's employee id is 5
//e1.version == 1 //e1.version == 1
e1 = findPartTimeEmp(5); e1 = findPartTimeEmp(5);

//Joe's current rate is $9


e1.raise(2);

tx1.commit();
Time

//e1.version == 2 in db //Joe's current rate is $9


if(e1.getRate() < 10)
//Joe's rate is $11 e1.raise(5);

//e1.version == 1 in db?
tx2.commit();
//Joe's rate is $14
//OptimisticLockException

34
Preventing Stale Data JPA 1.0

• Perform read or write locks on entities


• Prevents non-repeatable reads in JPA
entityManager.lock( entity, READ);
perform a version check on entity before commit
OptimisticLockException if mismatch
entityManager.lock( entity, WRITE);
perform a version check on entity
OptimisticLockException if mismatch
and increment version before commit

35

Preventing Stale Data

tx1.begin(); tx2.begin();
d1 = findDepartment(dId);
e1 = findEmp(eId);
//d1's original name is d1 = e1.getDepartment();
//”Engrg” em.lock(d1, READ);
d1.setName(“MarketEngrg”); if(d1's name is “Engrg”)
e1.raiseByTenPercent()
Time

tx1.commit(); ;

//Check d1.version in db
tx2.commit();
//e1 gets the raise he does
//not deserve
//Transaction rolls back

36
Preventing Parallel Updates – 2
Write lock prevents parallel updates

tx1.begin(); tx2.begin();
d1 = findDepartment(dId);
e1 = findEmp(eId);
d1 = e1.getDepartment();
em.lock(d1, WRITE);
//version++ for d1

Time
//d1's original name is em.flush();
//”Engrg” if(d1's name is “Engrg”)
d1.setName(“MarketEngrg”); e1.raiseByTenPercent();

tx1.commit();
//tx rolls back
tx2.commit();

37

Bulk Updates
• Update directly against the database, can be Faster But
> By pass EntityManager
> @Version will not be updated
> Entities in PC not updated

>tx.begin();
int id = 5; //Joe's employee id is 5
e1 = findPartTimeEmp(id); //Joe's current rate is $9

//Double every employee's salary


em.createQuery(
“Update Employee set rate = rate *
2”).executeUpdate();

//Joe's rate is still $9 in this persistence context


if(e1.getRate() < 10)
e1.raiseByFiveDollar();

tx.commit();
//Joe's salary will be $14
38
JPA 2.0 Locks

• JPA1.0 only supported optimistic locking, JPA 2.0 also


supports pessimistic locks
• JPA 2.0 LockMode values :
> OPTIMISTIC (= READ)
> OPTIMISTIC_FORCE_INCREMENT (= WRITE)
> PESSIMISTIC database locks the row
> PESSIMISTIC_FORCE_INCREMENT (SELECT . . . FOR UPDATE )
• Multiple places to specify lock

39

JPA 2.0 Locking


//Read then lock:
Account acct = em.find(Account.class, acctId);
// Decide to withdraw $100 so lock it for update
em.lock(acct, PESSIMISTIC); Lock after read, risk stale, could cause Opt
int balance = acct.getBalance(); Exception
acct.setBalance(balance - 100);

//Read and lock:


Locks longer,
Account acct = em.find(Account.class,
acctId,PESSIMISTIC); could cause
bottlenecks,
// Decide to withdraw $100 (already locked)
deadlock
int balance = acct.getBalance();
acct.setBalance(balance - 100);

40
JPA 2.0 Locking
Trade-offs:
lock earlier : risk bad scalability, deadlock

Lock later : risk stale data for update, get optimistic lock exception

// read then lock and refresh


Account acct = em.find(Account.class, acctId);
// Decide to withdraw $100 - lock and refresh
em.refresh(acct, PESSIMISTIC);
int balance = acct.getBalance();
acct.setBalance(balance - 100);

“right” approach depends on requirements

41

L2 cache shared across transactions and users


Putting it all together

User Session User Session User Session

Persistence Context Persistence Context Persistence Context


(EntityManager) (EntityManager) (EntityManager)

L2 Cache (EntityManagerFactory)
(Shared Cache)

Entity managers for a specific PersistenceUnit on a given Java Virtual Machine (JVM™)

42
Second-level Cache
• L2 Cache shares entity state across various
persistence contexts
> If caching is enabled, entities not found in persistence
context, will be loaded from L2 cache, if found
• Best for read-mostly classes
• L2 Cache is Vendor specific
> Java Persistence API 1.0 does not specify L2 support
> Java Persistence API 2.0 has basic cache operations
> Most persistence providers-- Hibernate, EclipseLink,
OpenJPA ... provide second-level cache(s)

43

L2 Cache

User transaction 1 User transaction 2

same entity
not shared

Persistence Context Persistence Context


Shared entity

Entity Entity

L2 on
query that looks for a single object based Cache
Id will go 1st to PC then to L2 cache, other q

Data source
44
L2 Caching
• Pros:
> avoids database access for already loaded entities
 faster for reading frequently accessed unmodified entit
• Cons
> memory consumption for large amount of objects
> Stale data for updated objects
> Concurrency for write (optimistic lock exception, or pessim
 Bad scalability for frequent or concurrently updated ent

45

L2 Caching
• Configure L2 caching for entities that are
> read often
> modified infrequently
> Not critical if stale
• protect any data that can be concurrently modified with a lo
> Must handle optimistic lock failures on flush/commit
> configure expiration, refresh policy to minimize lock failur
• Configure Query cache
> Useful for queries that are run frequently with the same p

46
JPA 2.0 Shared Cache API
• entity cache shared across persistence unit
> Accessible from EntityManagerFactory
• Supports only very basic cache operations
> Can be extended by vendors
public class Cache {
//checks if object is in IdentityMap
public boolean contains(Class class, Object pk);
// invalidates object in the IdentityMap
public void evict(Class class, Object pk);
public void evict(Class class); // invalidates the class in the IdentityMap.
public void evictAll(); // Invalidates all classes in the IdentityMap
}
47

EclipseLink Caching Architecture

EclipseLink caches Entiti


EntityManager EntityManager
Factory

L1 Cache

PC Server
Cache
L2 Shared Cache Cache Coordination
JMS (MDB)
RMI
CORBA
IIOP

48
EclipseLink Extensions - L2 Caching
• Default: Entities read are L2 cached
• Cache Configuration by Entity type or Persistence Unit
> You can disable L2 cache
• Configuration Parameters
> Cache isolation, type, size, expiration, coordination, invalidation,
> Coordination (cluster-messaging)
 Messaging: JMS, RMI, RMI-IIOP, …
 Mode: SYNC, SYNC+NEW, INVALIDATE, NONE

49

Type=
EclipseLink Mapping Extensions
Full: objects never flushed un
@Entity weak: object will be garbage
@Table(name="EMPLOYEE")
@Cache (
type=CacheType.WEAK,
isolated=false,
expiry=600000,
alwaysRefresh=true, =true
disableHits=true, disables L2 cache
coordinationType=INVALIDATE_CHANGED_OBJECTS
)
public class Employee implements Serializable {
...
}
@Cache
 type, size,isolated, expiry, refresh, cache usage,
 Cache usage and refresh query hints

50
Hibernate L2 Cache
• Hibernate L2 cache is not configured by default
• Hibernate L2 does not cache Entities. Hibernate caches Id and state
• Hibernate L2 cache is pluggable
> EHCache, OSCache, SwarmCacheProvider (JVM)
> JBoss TreeCache Cluster
> Can plug in others like Terracotta

Cache Concurrency Strategy

51

Hibernate L2 Cache
not configured by default
<!-- optional configuration file parameter -->
net.sf.ehcache.configurationResourceName=/name_of_configuration_resource

@Entity
@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRIT
public Class Country {
private String name;
Cache Concurrency Strategy
...
must be supported by cache provider
}

52
OpenJPA L2 Caching
• OpenJPA L2 caches object data and JPQL query results
• Updated when data is loaded from database and after cha
• For cluster caches are notified when changes are made
• Can plug in implementations, such as Tangosol’s Coheren
• several cache eviction strategies:
> Time-to-live settings for cache instances
@Entity @DataCache(timeout=5000)
public class Person { ... }

53

Agenda

>Entity Manager
>Persistence Context
>Entities
>Schema and Queries
>Transaction

54
Maintaining Relationship
• Application bears the responsibility of maintaining
relationship between objects

deptA.getEmployees().add(e3);
Before After
Employee1 Employee1
Department A Department A
Employee2 Employee2
Inconsistent!

Department B Employee3 Department B Employee3

55

Example – Domain Model

@Entity public class Employee {


@Id private int id;
private String firstName;
private String lastName;
@ManyToOne(fetch=LAZY)
private Department dept;
...
}
@Entity public class Department {
@Id private int id;
private String name;
@OneToMany(mappedBy = "dept", fetch=LAZY)
private Collection<Employee> emps = new ...;
...
}

56
Example – Managing Relationship
INCORRECT
public int addNewEmployee(...) {
Employee e = new Employee(...);
Department d = new Department(1, ...);

e.setDepartment(d);
//Reverse relationship is not set
em.persist(e);
em.persist(d);

return d.getEmployees().size();
}

57

Example – Managing Relationship


CORRECT
public int addNewEmployee(...) {
Employee e = new Employee(...);
Department d = new Department(1, ...);

e.setDepartment(d);
d.getEmployees().add(e);
em.persist(e);
em.persist(d);

return d.getEmployees().size();
}

58
Navigating Relationships
Data fetching strategy
• EAGER – immediate
• LAZY – loaded only when needed
• LAZY is good for large objects and/or with
relationships with deep hierarchies

59

Lazy loading and JPA


@Entity public class Department {
@Id private int id;
@OneToMany(mappedBy = "dept")
private Collection<Employee> emps ;
...
}
• Default FetchType is LAZY for 1:m and m:n relationships
> benefits large objects and relationships with deep hierarchies
• However for use cases where data is needed can cause
n+1 selects
• LAZY – N + 1 problem:
SELECT d.id, ... FROM Department d // 1 time
SELECT e.id, ... FROM Employee e
WHERE e.deptId = ? // N times

60
Lazy loading and JPA
@Entity public class Department {
@Id private int id;
@OneToMany(mappedBy = "dept", fetch=EAGER)
private Collection<Employee> employees ;
...
}
• Relationship can be Loaded Eagerly Can cause Cartesian product
> But if you have several related relationships, could load too much !
OR
• Temporarily override the LAZY fetch type, use Join Fetch in a query:
@NamedQueries({ @NamedQuery(name="getItEarly",
query="SELECT d FROM Department d JOIN FETCH d.employees")})

public class Department{


.....
}

61

Lazy loading and JPA


• Capture generated SQL
> persistence.xml file:<property name="toplink.logging.level" value="FINE">
• Test run use cases and examine the SQL statements
> optimise the number of SQL statements executed!
> only retrieve the data your application needs!
• Lazy load large (eg BLOB) attributes and relationships that
are not used often
• Override to Eagerly load in use cases where needed

62
Navigating Relationships Detached
Entity

• Accessing a LAZY relationship from a detached entity


> If not loaded , Causes an exception
Persistence
• Solutions: Context
> Use JOIN FETCH Managed
Entity
> Or Set Fetch type to EAGER
> Or Access the collection before entity is detached:
d.getEmployees().size();

63

Navigating Relationships
Data fetching strategy
• Cascade specifies operations on relationships
> ALL, PERSIST, MERGE, REMOVE, REFRESH
> The default is do nothing
• Avoid MERGE, ALL with deep hierarchies
> If want to do it, limit the scope

64
Using Cascade
@Entity public class Employee {
@Id private int id; Employee
private String firstName;
private String lastName; cascade=ALL
@ManyToOne(cascade=ALL, fetch=LAZY)
private Department dept; Department
...
} X
@Entity public class Department {
@Id private int id;
private String name; DepartmentCode
@OneToMany(mappedBy = "dept"
cascade=ALL, fetch=LAZY)
private Collection<Employee> emps = new ...;
@OneToMany
private Collection<DepartmentCode> codes;
...
}

65

Agenda

>Entity Manager
>Persistence Context
>Entities
>Schema and Queries
>Transaction

66
Database design Basic foundation of performance
• Smaller tables use less disk, less memory, can give better
performance
> Use as small data types as possible
> use as small primary key as possible
> Vertical Partition:
 split large, infrequently used columns into a separate
one-to-one table
• Use good indexing
> Indexes Speed up Querys
> Indexes slow down Updates
> Index columns frequently used in Query Where clause

67

Normalization

• Normalization Eliminates redundant data


> updates are usually faster.
 there's less data to change.

• However Normalized database causes joins


for queries
> Queries maybe slower
> Normalize then maybe De-normalize
frequently read columns and cache them

68
Mapping Inheritance Hierarchies

Employee
---------------------------
int id
String firstName
String lastName
Department dept

PartTimeEmployee FullTimeEmployee
------------------------ -----------------------
int rate double salary

69

Single Table Per Class


Benefits @Inheritance(strategy=SINGLE_TABLE)
• Simple EMPLOYEE
---------------------------
• No joins required ID I
FIRSTNAME varchar(25
> can be fast for Queries LASTNAME varchar(25
DEPT_ID int FK,
Drawbacks RATE int NULL,
SALARY double NU
• Not normalized DISCRIM varchar(30

> Wastes space


• Requires columns corresponding
to subclasses' state to be null
• Table can have too many columns
> Larger tables= more data, can have
negative affects on performance

70
Joined Subclass @Inheritance(strategy=JOINED)
Benefits EMPLOYEE

• Normalized database ID int PK,


FIRSTNAME varchar(255),
> Better for storage LASTNAME varchar(255),
DEPT_ID int FK,
• Database view same as
domain model PARTTIMEEMPLOYEE

• Easy to evolve domain model ID int PK F


RATE int NULL
Drawbacks
FULLTIMEEMPLOYEE
• Queries cause joins
> Slower queries ID int PK F
SALARY double NULL
> Poor performance for deep
hierarchies, polymorphic queries
and relationships

71

Table Per Class


@Inheritance(strategy=TABLE_PER_CLASS)
Benefits
• No need for joins to read
PARTTIMEEMPLOYEE
entities of same type ID int P
> Faster reads FIRSTNAME varchar(255),
LASTNAME varchar(255),
DEPT_ID int FK,
Drawbacks RATE int NULL

• Not normalized FULLTIMEEMPLOYEE

> Wastes space ID int


FIRSTNAME varchar(255),
• Polymorphic queries cause LASTNAME varchar(255),
DEPT_ID int FK,
union (all employees) SALARY double NULL

> Poor performance


• This strategy is not mandatory

72
vertical partitioning CREATE TABLE Customer(

CREATE TABLE Customer ( Frequently user_id INT NOT NULL AUTO_INCREMENT

user_id INT NOT NULL AUTO_INCREMENT , email VARCHAR(80) NOT NULL


, email VARCHAR(80) NOT NULL referenced , display_name VARCHAR(50) NOT NULL
, display_name VARCHAR(50) NOT NULL , password CHAR(41) NOT NULL
, password CHAR(41) NOT NULL , PRIMARY KEY (user_id)
CREATE TABLE CustomerInfo (
, first_name VARCHAR(25) NOT NULL , UNIQUEuser_id
INDEX INT
(email)
NOT NULL
, last_name VARCHAR(25) NOT NULL ) ENGINE=InnoDB;
, first_name VARCHAR(25) NOT NULL
, address VARCHAR(80) NOT NULL , last_name VARCHAR(25) NOT NULL
, city VARCHAR(30) NOT NULL , address VARCHAR(80) NOT NULL
, province CHAR(2) NOT NULL
, postcode CHAR(7) NOT NULL
Less Frequently , city VARCHAR(30) NOT NULL
, province CHAR(2) NOT NULL
, interests TEXT NULL referenced, , postcode CHAR(7) NOT NULL
, bio TEXT NULL
, signature TEXT NULL
TEXT data , interests TEXT NULL
, bio TEXT NULL
, skills TEXT NULL
, signature TEXT NULL
, PRIMARY KEY (user_id)
, skills TEXT NULL
, UNIQUE INDEX (email)
, PRIMARY KEY (user_id)
) ENGINE=InnoDB;
, FULLTEXT KEY (interests, skills)
) ENGINE=MyISAM;
• limit number of columns per table
• split large, infrequently used columns into a separate table

73

Vertical partitioning
@Entity
public class Customer {
int userid;
String email; @Entity
String password; public class CustomerInfo {
@OneToOne(fetch=LAZY) int userid;
CustomerInfo info; String name;
} String interests;
@OneToOne(mappedBy=
"CustomerInfo")
Customer customer;
}
> split large, infrequently used columns into a separate table
74
Scalability: Sharding - Application Partitioning
Servers
Sharding Architecture
Web/App

Cust_id 1-999

Cust_id 1000-1999

Cust_id 2000-2999

> Sharding =Horizontal partitioning


 Split table by rows into partitions
75

Know what SQL is executed


• Capture generated SQL:
persistence.xml file:
<property name="toplink.logging.level" value="FINE">
• Find and fix problem SQL:
> Watch for slow Queries
 use the MySQL slow query log and use Explain
– Can reveal problems such as a missing Indexes
> Watch for Queries that execute too often to load needed data
> Watch for loading more data than needed

76
MySQL Query Analyser

Find and fix problem SQL:


• how long a query took Its not just slow running queries that are a
• results of EXPLAIN statements

• Historical and real-time analysis


> query execution counts, run time

77

Agenda

>Entities
>Entity Manager
>Persistence Context
>Queries
>Transaction

78
Query Types – 1
• Named query
> Like findByXXXX() from EntityBeans
> Compiled by persistence engine
> Created either with @NamedQuery or externalized in
orm.xml
• Dynamic query
> Created dynamically by passing a query string to
EntityManager
Query query = em.createQuery(“select ...”);
> Beware of SQL injection, better to use with named NOT GOOD
q parameters
= em.createQuery(“select e from Employee e WHERE ”
+ “e.empId LIKE '” + id + “'”);
GOOD
q = em.createQuery(“select e from Employee e WHERE ”
+ “e.empId LIKE ':id'”);
q.setParameter(“id”, id);

79

Query Types – 2
• Native query
> Leverage the native database querying facilities
> Not portable – ties queries to database

80
Flush Mode
• Controls whether the state of managed entities are
synchronized before a query
• Types of flush mode
> AUTO – immediate, default
> COMMIT – flush only when a transaction commits
> NEVER – need to invoke EntityManger.flush() to
flush
//Assume JTA transaction
Order order = em.find(Order.class, orderNumber);
em.persist(order);
Query q = em.createNamedQuery(“findAllOrders”);
q.setParameter(“id”, orderNumber);
q.setFlushMode(FlushModeType.COMMIT);
//Newly added order will NOT visible
List list = q.getResultList();

81

Agenda

>Entities
>Entity Manager
>Persistence Context
>Queries
>Transaction

82
Transactions
• Do not perform expensive and unnecessary
operations that are not part of a transaction
> Hurt performance
> Eg. logging – disk write are expensive, resource contention
on log
• Do not use transaction when browsing data
> @TransactionAttribute(NOT_SUPPORTED)

83

Carol McDonald
Java Architect

84
84
Dynamic,typesafequeriesinJPA2.0
How the Criteria API builds dynamic queries and reduces run-time failures

The Java developer community has welcomed JPA since its introduction in 2006. The next
major update of the specification — version 2.0 (JSR 317) — will be finalized later in 2009
(see Resources). One of the key features introduced in JPA 2.0 is the Criteria API, which brings
a unique capability to the Java language: a way to develop queries that a Java compiler can
verify for correctness at compile time. The Criteria API also includes mechanisms for building
queries dynamically at run time.

This article introduces the Criteria API and the closely associated metamodel concept. You will
learn how to use the Criteria API to develop queries that a Java compiler can check for
correctness to reduce run-time errors, in contrast to string-based Java Persistence Query
Language (JPQL) queries. And through example queries that use database functions or match
a template instance, I'll demonstrate the added power of programmatic query-construction
mechanics compared to JPQL queries that use a predefined grammar. The article assumes you
have a basic familiarity with Java language programming and common JPA usage such
as EntityManagerFactory or EntityManager.

What's wrong with this JPQL query?


JPA 1.0 introduced JPQL, a powerful query language that's considered a major reason for JPA's
popularity. However, JPQL — being a string-based query language with a definite grammar —
has a few limitations. To understand one of the major limitations, consider the simple code
fragment in Listing 1, which executes a JPQL query to select the list of Persons older than 20
years:

Listing 1. A simple (and wrong) JPQL query


EntityManager em = ...;
String jpql = "select p from Person where p.age > 20";
Query query = em.createQuery(jpql);
List result = query.getResultList();

This basic example shows the following key aspects of the query-execution model in JPA 1.0:
x A JPQL query is specified as a String (line 2).
x EntityManager is the factory that constructs an executable query instance given a JPQL
string (line 3).
x The result of query execution consists of the elements of an untyped java.util.List.

But this simple example has a serious error. Effectively, the code will compile happily, but it
will fail at run time because the JPQL query string is syntactically incorrect. The correct syntax
for the second line of Listing 1 is:
String jpql = "select p from Person p where p.age > 20";

Unfortunately, the Java compiler has no way to detect such an error. The error will be
encountered at run time at line 3 or line 4 (depending on whether the JPA provider parses a
JPQL string according to JPQL grammar during query construction or execution).
How doe es a typesaffe query hellp?
One of th
he major adv vantages of the
t Criteria API is that iit prohibits tthe construcction of querries
that are syntactically
y incorrect. Listing
L 2 rew
writes the JP
PQL query in n Listing 1 u
using
the CriteriaQuery intterface:

2 Basic steps of writin


Listing 2. ng a Criteria
aQuery
EntityManager em = ...
QueryBu uilder qb = em.getQuery
e yBuilder();
CriteriaQ
Query<Perso on> c = qb.ccreateQuery((Person.classs);
Root<Person> p = c.from(Person n.class);
Predicatte condition = qb.gt(p.get(Person_.agge), 20);
c.where(c
condition);
TypedQu uery<Person n> q = em.createQuery(c c);
List<Pers
son> result = q.getResulltList();

Listing 2 illustrates the


t Criteria API's core co
onstructs an
nd demonstrrates its bas sic usage:
x Line 1 obtain ns an EntityM
Manager insstance by on
ne of the seveeral availablle means.

x In
n line 2, EnttityManager creates an instance
i of Q
QueryBuildeer. QueryBuiilder is the
fa
actory for CrriteriaQuery..

x In
n line 3, the QueryBuildder factory co onstructs a CriteriaQue ry instance.
A CriteriaQue ery is generiically typed. The genericc type argum
ment declares the type off
re
esult this CrriteriaQuery will return upon
u executtion. You ca
an supply va arious kinds of
re
esult-type arrguments — from a pers sistent entity
y such as Peerson.class tto a more fre
ee-
fo
orm one such asObject[] — while constructing a CriteriaQu uery.

x In
n line 4, que
ery expressio o the CriterriaQuery instance. Querry expression
ons are set on ns
arre the core units
u or nod
des that are assembled
a in
n a tree to sspecify a CritteriaQuery.
Figure
F 1 showws the hiera
archy of querry expression
ns defined in n the Criteriia API:

Figure
F 1. Intterface hierrarchy of qu
uery expresssions
To begin with, the CriteriaQuery is set to query from Person.class. As a result,
a Root<Person> instance p is returned. Root is a query expression that denotes the
extent of a persistent entity. Root<T> essentially says: "Evaluate this query across all
instances of type T." It is similar to the FROM clause of a JPQL or SQL query. Also
notice thatRoot<Person> is generically typed. (Actually, every expression is.) The type
argument is the type of the value the expression evaluates to. So Root<Person> denotes
an expression that evaluates to Person.class.
x Line 5 constructs a Predicate. Predicate is another common form of query expression
that evaluates to either true or false. A predicate is constructed by the QueryBuilder,
which is the factory not only for CriteriaQuery, but also for query
expressions. QueryBuilder has API methods for constructing all kinds of query
expressions that are supported in traditional JPQL grammar, plus a few more.
In Listing 2, QueryBuilder is used to construct an expression that evaluates whether
the value of its first expression argument is numerically greater than the value of the
second argument. The method signature is:
Predicate gt(Expression<? extends Number> x, Number y);

This method signature is a fine example of how a strongly typed language such as the
Java language can be judiciously used to define an API that allows you to express what
is correct and prohibits what is not. The method signature specifies that it is possible to
compare an expression whose value is a Number only to another Number (and not, for
example, to a String):
Predicate condition = qb.gt(p.get(Person_.age), 20);

But there is more to line 5. Notice the qb.gt() method's first input
argument: p.get(Person_.age), where p is theRoot<Person> expression obtained
previously. p.get(Person_.age) is a path expression. A path expression is the result of
navigation from a root expression via one or more persistent attribute(s).

Hence p.get(Person_.age)denotes a path expression by navigating from the root


expression p by the age attribute of Person. You may wonder what Person_.age is. For
the time being, assume it is a way to denote the age attribute of Person. I'll elaborate on
the meaning of Person_.age when I discuss the new Metamodel API introduced in JPA
2.0.

As I mentioned earlier, every query expression is generically typed to denote the type of
the value the expression evaluates to. The path expression p.get(Person_.age) evaluates
to an Integer if the age attribute in Person.classis declared to be of type Integer (or int).
Because of the type safety inherent in the API, the compiler itself will raise an error for a
meaningless comparison, such as:
Predicate condition = qb.gt(p.get(Person_.age, "xyz"));

x Line 6 sets the predicate on the CriteriaQuery as its WHERE clause.


x In line 7, EntityManager creates an executable query given an input CriteriaQuery. This
is similar to constructing an executable query given a JPQL string as input. But
because the input CriteriaQuery carries richer type information, the result is
a TypedQuery that is an extension of the familiar javax.persistence.Query.
The TypedQuery, as the name suggests, knows the type it returns as a result of its
execution. It is defined as:
public interface TypedQuery<T> extends Query {
List<T> getResultList();
}
As
A opposed to o correspond
ding untyped super-inteerface:
puublic interfa
ace Query {
Liist getResulttList();
}

Naturally,
N the
e TypedQuerry result has s the same P Person.classs type specifi
fied during thhe
co
onstruction of the inputtCriteriaQue ery by a QueeryBuilder (liine 3).
x In
n line 8, the type inform s carried thrroughout shows its adva
mation that is antage when n the
quuery is finally executed to get a list of results. T
The result is a typed listt of Persons that
sa
aves the dev veloper of tro
ouble of an extra
e (and offten ugly) ca
ast (and minnimizes the rrisk
off ClassCastE Exception errror at run tiime) while itterating thro
ough the ressultant eleme ents.

To summ
marize the baasic aspects of the simple example iin Listing 2:
x CriteriaQuery
C y is a tree off query-expre
ession nodess that are used to specify query clau
uses
su
uch as FROM M, WHERE, andORDER R BY in a tra
aditional striing-based qu
uery languagge.
Figure
F 2 show
ws the claus ses related to
o a query:

Figure
F 2. CriiteriaQuery
y encapsulattes the clau
uses of a tra
aditional qu
uery

x The query exp


pressions arre generically y typed. A feew typical ex
xpressions a are:
o Root<T>, which is s equivalent to a FROM clause.
o Predic cate, which evaluates
e to a Boolean vvalue of truee or false. (In
n fact, it is
declarred as interfface Predicatte extends E Expression<B Boolean>.)
o Path<T>, which denotes
d a perrsistent attriibute naviga
ated from
a Root<?> express sion. Root<TT> is a speciialPath<T> w with no parent.
x QueryBuilder
Q r is the facto
ory for CriterriaQuery and d query expressions of a all sorts.

x CriteriaQuery
C y is transferrred to an executable qu ery with its type information preserrved
so
o that the ellements of thhe selected list
l can be a
accessed withhout any runn-time castiing.
Metamodel of a persistent domain
The discussion of Listing 2 points out an unusual construct: Person_.age, which is a
designation for the persistent ageattribute of Person. Listing 2 uses Person_.age to form a path
expression navigating from a Root<Person> expression p byp.get(Person_.age). Person_.age is a
public static field in the Person_ class, and Person_ is the static, instantiated, canonical
metamodel class corresponding to the original Person entity class.

A metamodel class describes the meta information of a persistent class. A metamodel class
is canonical if the class describes the meta information of a persistent entity in the exact
manner stipulated by the JPA 2.0 specification. A canonical metamodel class is static in the
sense all its member variables are declared static (and public). The Person_.age is one such
static member variable. You instantiate the canonical class by generating a
concrete Person_.java at a source-code level at development time. Through such instantiation,
it is possible to refer to persistent attributes of Person at compile time, rather than at run time,
in a strongly typed manner.

This Person_ metamodel class is an alternative means of referring to meta information


of Person. This alternative is similar to the much-used (some may say, abused) Java Reflection
API, but with a major conceptual difference. You can use reflection to obtain the meta
information about an instance of a java.lang.Class, but meta information
about Person.class cannot be referred to in a way that a compiler can verify. For example,
using reflection, you'd refer to the field named age in Person.classwith:
Field field = Person.class.getField("age");

However, this technique is fraught with a limitation similar to the one you observed in the case
of the string-based JPQL query inListing 1. The compiler feels happy about this piece of code
but cannot verify whether it will work. The code can fail at run time if it includes even a simple
typo. Reflection will not work for what JPA 2.0's typesafe query API wants to accomplish.

A typesafe query API must enable your code to refer to the persistent attribute named age in
a Person class in a way that a compiler can verify at compile time. The solution that JPA 2.0
provides is the ability to instantiate a metamodel class namedPerson_ that corresponds
to Person by exposing the same persistent attributes statically.
Any discussion about meta or meta-meta information often induces somnolence. So I'll present
a concrete example of a metamodel class for a familiar Plain Old Java Object (POJO) entity
class — domain.Person, shown in Listing 3:

Listing 3. A simple persistent entity


package domain;
@Entity
public class Person {
@Id
private long ssn;
private string name;
private int age;

// public gettter/setter methods


public String getName() {...}
}

This is a typical definition of a POJO, with annotations — such as @Entity or @Id — that
enable a JPA provider to manage instances of this class as persistent entities.
The corresponding static canonical metamodel class of domain.Person is shown in Listing 4:
Listing 4. Canonical metamodel for a simple entity
package domain;
import javax.persistence.metamodel.SingularAttribute;

@javax.persistence.metamodel.StaticMetamodel(domain.Person.class)

public class Person_ {


public static volatile SingularAttribute<Person,Long> ssn;
public static volatile SingularAttribute<Person,String> name;
public static volatile SingularAttribute<Person,Integer> age;
}

The metamodel class declares each persistent attribute of the original domain.Person entity as
a static public field ofSingularAttribute<Person,?> type. Making use of this Person_ metamodel
class, I can refer to the persistent attribute ofdomain.Person named age — not via the
Reflection API, but as a direct reference to the static Person_.age field — at compile time. The
compiler can then enforce type checking based on the declared type of the attribute named age.

I've already cited an example of such a restriction: QueryBuilder.gt(p.get(Person_.age),


"xyz") will cause a compiler error because the compiler can determine from the signature
of QueryBuilder.gt(..) and type of Person_.age that a Person's age is a numeric field and cannot
be compared against a String.

A few other key points to notice are:


x The metamodel Person_.age field is declared to be of
type javax.persistence.metamodel.SingularAttribute. SingularAttribute is one of the
interfaces defined in the JPA Metamodel API, which I'll describe in the next section. The
generic type arguments of a SingularAttribute<Person, Integer> denote the class that
declares the original persistent attribute and the type of the persistent attribute itself.

x The metamodel class is annotated as @StaticMetamodel(domain.Person.class) to


designate it as a metamodel class corresponding to the original
persistent domain.Person entity.

The Metamodel API


I've defined a metamodel class as a description of a persistent entity class. Just as the
Reflection API requires other interfaces — such
as java.lang.reflect.Field or java.lang.reflect.Method — to describe the constituents
ofjava.lang.Class, so the JPA Metamodel API requires other interfaces, such
as SingularAttribute, PluralAttribute, to describe a metamodel class's types and their
attributes.
Figure 3 shows the interfaces defined in the Metamodel API to describe types:
Figure 3.
3 Interface hierarchy for
f persisten
nt types in the Metam
model API

Figure 4 shows the interfaces de


efined in the Metamodel API to describe attributtes:

Figure 4.
4 Interface hierarchy of
o persisten
nt attributess in the Mettamodel AP
PI

The interrfaces of JPAA's Metamod del API are more


m specialiized than th
hose of the Ja ava Reflectio
on
API. Thiss finer distin
nction is requ
uired to exprress rich meeta informatiion about pe ersistence. F
For
example,, the Java Re eflection APII represents all Java typ
pes asjava.laang.Class. Th hat is, no sp
pecial
distinctio
on is made via
v separate definitions among
a conccepts such a as class, absttract class, aand
an interfa
face. Of courrse, you can ask a Class s whether it is an interfaace or if it is abstract — but
that is noot the same as represen nting the conncept of interrface differe ntly from ann abstract cllass
via two separate defiinitions.

The Javaa Reflection API


A was intrroduced at th he inceptionn of the Java
a language (a and was quiite a
pioneerin
ng concept at
a that time for
f a commo on general-ppurpose prog gramming la anguage), bu ut
awarenesss of the usee and power of strongly typed system ms has prog gressed over the years. T The
JPA Metaamodel API harnesses
h th
hat power to
o introduce sstrong typinng for persisttent entities.. For
example,, persistent entities
e are semantically
s y distinguish
hed as Mapp pedSuperCla ass, Entity,
and Emb beddable. Beefore JPA 2.0 0, this sema
antic distincttion was rep
presented via a correspond ding
class-leve
el annotations in the pe ersistent-classs definition
n. JPA Metammodel descriibes three
separate interfaces — MappedSu uperclassTyp pe, EntityTyype, and Em
mbeddableTyp pe — in
thejavax..persistence.metamodel package to bring their ssemantic sp pecialties into sharper fo ocus.
Similarly
y, the persisttent attributtes are distin
nguished at type-definittion level via
a interfaces s
such
as SingularAttribute, CollectionA Attribute, anndMapAttrib bute.

om the aesth
Aside fro hetics of desccription, the
ese specializeed metamoddel interfaces
s have practtical
advantagges that help
p to build typ
pesafe queriies and reduuce the channce of run-tim
me errors.
You've se
een some of these advan ntages in thee earlier exammples, and y
you will see more of the
em
when I describe exammples of join
ns using CritteriaQuery.

Run-timme scope
Broadly speaking,
s on
ne can draw some paralllels between n the traditio
onal interfac
ces of the Ja ava
Reflection
n API and th he interfacess ofjavax.perrsistence.meetamodel speecialized to ddescribe
persisten
nce metadata a. To furtherr the analog
gy, an equivaalent conceppt of run-tim
me scope is
needed foor the metam model interfafaces. The javva.lang.Classs instancess are scoped
byjava.la
ang.ClassLoa ader at run time.
t A set of
o Java classs instances tthat referencce one anoth her
must all be defined under
u the sc
cope of a ClaassLoader. TThe set bounndaries are sstrict or close
ed in
the sensee that if a class A defineed under the e scope ofClaassLoader L tries to refe
er to class B,,
which is not under the scope of ClassLoaderr L, the resu ult is a
dreadedC ClassNotFou undException n or NoClass sDef FoundE Error (and ooften sleep d
deprivation fo or a
developerr or deployer for environ nments with h multiple CllassLoaders)).

This notiion of run-time scope as s a strict set of mutually


y referable cllasses is capptured in JPPA
1.0 as a persistence
p unit. The sco
ope of a pers sistence uniit in terms o
of its persiste
ent entities iis
enumera ated in the <class> claus se of a META A-INF/persisstence.xml fifile. In JPA 22.0, the scop
pe is
made ava ailable to the
e developer at run time via
the javaxx.persistencee.metamodell.Metamodellinterface. T The Metamod del interface is the holdeer of
all persis
stent entities
s known to a specific persistence un nit, as illustrrated in Figu
ure 5:

Figure 5.
5 Metamode
el interface
e is the conttainer of ty nit
ypes in a perrsistence un

This inteerface lets th


he metamode b accessed by their corrresponding persistent-e
el elements be entity
class. Foor example, tot obtain a reference
r to the
t persisten nt metadata
a for a Person persistentt
entity, yo
ou can write e:
EntityMa anagerFactorry emf = ...;
Metamod del metamod del = emf.gettMetamodel();
EntityTyp pe<Person> pClass = me etamodel.enntity(Person.cclass);

This is annalogous, with


w slightly different
d stylle and idiom
ms, to obtain
ning a Class by its name
e
via ClasssLoader:
ClassLoaader classloaader = Threa ad.currentTh hread().getCContextClasssLoader();
Class<?>> clazz = clas
ssloader.loaddClass("dom main.Person" );
EntityType<Person> can be browsed at run time to get the persistent attributes declared in
the Person entity. If the application invokes a method on pClass such
as pClass.getSingularAttribute("age", Integer.class), it will return aSingularAttribute<Person,
Integer> instance that is effectively the same as the static Person_.age member of the
instantiated canonical metamodel class. Essentially, the persistent attribute that the
application can refer to at run time via the Metamodel API is made available to a Java compiler
by instantiation of the static canonical metamodel Person_ class.

Apart from resolving a persistent entity to its corresponding metamodel elements, the
Metamodel API also allows access to all the known metamodel classes
(Metamodel.getManagedTypes()) or access to a metamodel class by its persistence-specific
information — for example embeddable(Address.class), which returns
a EmbeddableType<Address> instance that is a subinterface of ManagedType<>.

In JPA, the meta information about a POJO is further attributed with persistent specific meta
information — such as whether a class is embedded or which fields are used as primary key —
with source-code level annotations (or XML descriptors). The persistent meta information falls
into two broad categories: for persistence (such as @Entity) and for mapping (such as@Table).
In JPA 2.0, the metamodel captures the metadata only for persistence annotations — not for
the mapping annotation. Hence, with the current version of the Metamodel API, it's possible to
know which fields are persistent, but it's not possible to find out which database columns they
are mapped to.

Canonical vs. non-canonical


Although the JPA 2.0 specification stipulates the exact shape of a canonical static metamodel
class (including the metamodel class's fully qualified name and the names of its static fields), it
is entirely possible for an application to write these metamodel classes as well. If the
application developer writes the metamodel classes, they are called non-canonical metamodel.
Currently, the specification for non-canonical metamodel is not very detailed, and support for
non-canonical metamodel can be nonportable across the JPA providers. You may have noticed
that the public static fields are only declared in canonical metamodel but not initialized. The
declaration makes it possible to refer to these fields during development of aCriteriaQuery. But
they must be assigned a value to be useful at run time. While it is the responsibility of the JPA
provider to assign values to these fields for canonical metamodel, similar warranty is not
extended for non-canonical metamodel. Applications that use non-canonical metamodel must
either depend on specific vendor mechanisms or devise their own mechanics to initialize the
field values to metamodel attributes at run time.

Code generation and usability

Automatic source-code generation often raises eyebrows. The case of generated source code for
canonical metamodel adds some concerns. The generated classes are used during
development, and other parts of the code that build the CriteriaQuerydirectly refer to them at
compile time, leaving some usability questions:
x Should the source-code files be generated in the same directory as the original source,
in a separate directory, or relative to the output directory?
x Should the source-code files be checked in a version-controlled configuration-
management system?
x How should the correspondence between an original Person entity definition and its
canonical Person_ metamodel be maintained? For example, what if Person.java is
edited to add an extra persistent attribute, or refactored to rename a persistent
attribute?
The answers to these questions are not definitive at the time of this writing.

Annotation processing and metamodel generation


Quite naturally, if you have many persistent entities you will not be inclined to write the
metamodel classes yourself. The persistence provider is expected to generate these metamodel
classes for you. The specification doesn't mandate such a facility or the generation mechanics,
but an implicit understanding among JPA providers is that they'll generate the canonical
metamodel using the Annotation Processor facility integrated in the Java 6 compiler. Apache
OpenJPA provides a utility to generate these metamodel classes either implicitly when you
compile the source code for persistent entities or by explicitly invoking a script. Prior to Java 6,
an annotation processor tool called apt was available and widely used — but with Java 6, the
coupling between compiler and Annotation Processor is defined as part of the standard.
The process of generating these metamodel classes in OpenJPA as your persistence provider is
as simple as compiling the POJO entity with OpenJPA class libraries in the compiler's
classpath:
$ javac domain/Person.java

The canonical metamodel Person_ class will be generated, written in the same source directory
as Person.java, and compiled as a side-effect of this compilation.

Writing queries in a typesafe manner


So far, I've established the components of CriteriaQuery and its associated metamodel classes.
Now I'll show you how to develop some queries with the Criteria API.

Functional expressions
Functional expressions apply a function to one or more input arguments to create a new
expression. The functional expression's type depends on the nature of the function and type of
its arguments. The input arguments themselves can be expressions or literal values. The
compiler's type-checking rules coupled with the API's signature govern what constitutes
legitimate input.
Consider a single-argument expression that applies averaging on its input expression. Listing 5
shows the CriteriaQuery to select the average balance of all Accounts:

Listing 5. Functional expression in CriteriaQuery


CriteriaQuery<Double> c = cb.createQuery(Double.class);
Root<Account> a = c.from(Account.class);
c.select(cb.avg(a.get(Account_.balance)));

An equivalent JPQL query would be:


String jpql = "select avg(a.balance) from Account a";

In Listing 5, the QueryBuilder factory (represented by the variable cb) creates


an avg() expression and uses that expression in the query's select() clause.
The query expression is a building block that can be assembled to define the final selection
predicate for the query. The example in Listing 6 shows a Path expression created by
navigating to the balance of Account, and then the Path expression is used as an input
expression in a couple of binary functional expressions — greaterThan() and lessThan() — both
of which result in a Boolean expression or simply a predicate. The predicates are then
combined via an and() operation to form the final selection predicate to be evaluated by the
query's where() clause:

Fluent API
As this example shows, the Criteria API methods often return the type that can be directly used
in a related method, thereby providing a popular programming style known as Fluent API.

Listing 6. where() predicate in CriteriaQuery


CriteriaQuery<Account> c = cb.createQuery(Account.class);
Root<Account> account = c.from(Account.class);
Path<Integer> balance = account.get(Account_.balance);
c.where(cb.and
(cb.greaterThan(balance, 100),
cb.lessThan(balance), 200)));

An equivalent JPQL query would be:


"select a from Account a where a.balance>100 and a.balance<200";

Complex predicates
Certain expressions — such as in() — apply to a variable number of expressions. Listing 7
shows an example:

Listing 7. Multivalued expression in CriteriaQuery


CriteriaQuery<Account> c = cb.createQuery(Account.class);
Root<Account> account = c.from(Account.class);
Path<Person> owner = account.get(Account_.owner);
Path<String> name = owner.get(Person_.name);
c.where(cb.in(name).value("X").value("Y").value("Z"));

This example navigates from Account via two steps to create a path expression representing the
name of an account's owner. Then it creates an in() expression with the path expression as
input. The in() expression evaluates if its input expression equals any of its variable number of
arguments. These arguments are specified through the value() method on the In<T>expression,
which has the following method signature:
In<T> value(T value);

Notice how Java generics are used to specify that an In<T> expression can be evaluated for
membership only with values of type T. Because the path expression representing
the Account owner's name is of type String, the only valid comparison is against String-valued
arguments, which can be either a literal or another expression that evaluates to String.
Contrast the query in Listing 7 with the equivalent (correct) JPQL:
"select a from Account a where a.owner.name in ('X','Y','Z')";

A slight oversight in the JPQL will not only be undetected by the compiler but also will produce
an unintended outcome. For example:
"select a from Account a where a.owner.name in (X, Y, Z)";
Joining relationships
Although the examples in Listing 6 and Listing 7 use expressions as the building blocks, the
queries are based on a single entity and its attributes. But often queries involve more than one
entity, which requires you to join two or more entities.CriteriaQuery expresses joining two
entities by typed join expressions. A typed join expression has two type parameters: the type
you are joining from and the bindable type of the attribute being joined. For example, if you
want to query for the Customers whose one or more PurchaseOrder(s) are not delivered yet,
you need to express this by an expression that joins Customer toPurchaseOrders,
where Customer has a persistent attribute named orders of type java.util.Set<PurchaseOrder>,
as shown in Listing 8:

Listing 8. Joining a multivalued attribute


CriteriaQuery<Customer> q = cb.createQuery(Customer.class);
Root<Customer> c = q.from(Customer.class);
SetJoin<Customer, PurchaseOrder> o = c.join(Customer_.orders);

The join expression created from the root expression c and the persistent
Customer.orders attribute is parameterized by the source of join — that is, Customer — and
the bindable type of the Customer.orders attribute, which is PurchaseOrder andnot the
declared type java.util.Set<PurchaseOrder>. Also notice that because the original attribute is of
typejava.util.Set, the resultant join expression is SetJoin, which is a specialized Join for an
attribute of declared typejava.util.Set. Similarly, for other supported multivalued persistent
attribute types, the API defines CollectionJoin,ListJoin, and MapJoin. (Figure 1 shows the
various join expressions.) There is no need for an explicit cast in the third line inListing
8 because CriteriaQuery and the Metamodel API recognize and distinguish attribute types that
are declared asjava.util.Collection or List or Set or Map by overloaded methods for join().

The joins are used in queries to form a predicate on the joined entity. So if you want to select
the Customers with one or more undelivered PurchaseOrder(s), you can define a predicate by
navigating from the joined expression o via its status attribute, comparing it with
DELIVERED status, and negating the predicate as:
Predicate p = cb.equal(o.get(PurchaseOrder_.status), Status.DELIVERED)
.negate();

One noteworthy point about creating a join expression is that every time you join from an
expression, it returns a new join expression, as shown in Listing 9:

Listing 9. Every join creates a unique instance


SetJoin<Customer, PurchaseOrder> o1 = c.join(Customer_.orders);
SetJoin<Customer, PurchaseOrder> o2 = c.join(Customer_.orders);
assert o1 == o2;

The assertion in Listing 9 for equality of two join expressions from the same expression c with
the same attribute will fail. Thus, if a query involves a predicate for PurchaseOrders that are
not delivered and whose value is more than $200, then the correct construction is to
join PurchaseOrder with the root Customer expression only once, assign the resultant join
expression to a local variable (equivalent to a range variable in JPQL terminology), and use the
local variable in forming the predicate.
Using parameters
Take a look back at this article's original JPQL query (the correct one):
String jpql = "select p from Person p where p.age > 20";

Though queries are often written with constant literals, it is not a good practice. The good
practice is to parameterize a query, which allows the query to be parsed or prepared only once,
cached, and reused. So a better way to write the query is to use a named parameter:
String jpql = "select p from Person p where p.age > :age";

A parameterized query binds the value of the parameter before the query execution:
Query query = em.createQuery(jpql).setParameter("age", 20);
List result = query.getResultList();

In a JPQL query, the parameters are encoded in the query string as either named (preceded by
a colon — for example, :age) or positional (preceded by a question mark — for example, ?3).
In CriteriaQuery, the parameters themselves are query expressions. Like any other expression,
they are strongly typed and constructed by the expression factory — namely,QueryBuilder. The
query in Listing 2, then, can be parameterized as shown in Listing 10:

Listing 10. Using parameters in a CriteriaQuery

ParameterExpression<Integer> age = qb.parameter(Integer.class);


Predicate condition = qb.gt(p.get(Person_.age), age);
c.where(condition);
TypedQuery<Person> q = em.createQuery(c);
List<Person> result = q.setParameter(age, 20).getResultList();

To contrast the usage of parameters to that of JPQL: the parameter expression is created with
explicit type information to be anInteger and is directly used to bind a value of 20 to the
executable query. The extra type information is often useful for reducing run-time errors,
because it prohibits the parameter from being compared against an expression of an
incompatible type or being bound with a value of an inadmissible type. Neither form of compile-
time safety is warranted for the parameters of a JPQL query.

The example in Listing 10 shows an unnamed parameter expression that is directly used for
binding. It is also possible to assign a name to the parameter as the second argument during
its construction. In that case, you can bind the parameter value to the query using that name.
What is not possible, however, is use of positional parameters. Integral position in a (linear)
JPQL query string makes some intuitive sense, but the notion of an integral position cannot be
carried forward in the context ofCriteriaQuery, where the conceptual model is a tree of query
expressions.

Another interesting aspect of JPA query parameters is that they do not have intrinsic value. A
value is bound to a parameter in the context of an executable query. So it is perfectly legal to
create two separate executable queries from the same CriteriaQueryand bind two different
integer values to the same parameter for these executable queries.
Projecting the result
You've seen that the type of result a CriteriaQuery will return upon execution is specified up
front when a CriteriaQuery is constructed by QueryBuilder. The query's result is specified as
one or more projection terms. There are two ways to specify the projection term on
the CriteriaQuery interface:
CriteriaQuery<T> select(Selection<? extends T> selection);
CriteriaQuery<T> multiselect(Selection<?>... selections);

The simplest and often used projection term is the candidate class of the query itself. It can be
implicit, as shown in Listing 11:

Listing 11. CriteriaQuery selects candidate extent by default

CriteriaQuery<Account> q = cb.createQuery(Account.class);
Root<Account> account = q.from(Account.class);
List<Account> accounts = em.createQuery(q).getResultList();

In Listing 11, the query from Account does not explicitly specify its selection term and is the
same as explicitly selecting the candidate class. Listing 12 shows a query that uses an explicit
selection term:

Listing 12. CriteriaQuery with explicit single selection term

CriteriaQuery<Account> q = cb.createQuery(Account.class);
Root<Account> account = q.from(Account.class);
q.select(account);
List<Account> accounts = em.createQuery(q).getResultList();

When the projected result of the query is something other than the candidate persistent entity
itself, several other constructs are available to shape the result of the query. These constructs
are available in the QueryBuilder interface, as shown in Listing 13:

Listing 13. Methods to shape query result

<Y> CompoundSelection<Y> construct(Class<Y> result, Selection<?>... terms);


CompoundSelection<Object[]> array(Selection<?>... terms);
CompoundSelection<Tuple> tuple(Selection<?>... terms);

The methods in Listing 13 build a compound projection term composed of other selectable
expressions. The construct()method creates an instance of the given class argument and
invokes a constructor with values from the input selection terms. For example,
if CustomerDetails — a nonpersistent entity — has a constructor that
takes String and int arguments, then aCriteriaQuery can return CustomerDetails as its result
by creating instances from name and age of selected Customer — a persistent entity —
instances, as shown in Listing 14:

Listing 14. Shaping query result into instances of a class by construct()

CriteriaQuery<CustomerDetails> q = cb.createQuery(CustomerDetails.class);
Root<Customer> c = q.from(Customer.class);
q.select(cb.construct(CustomerDetails.class,
c.get(Customer_.name), c.get(Customer_.age));
Multiple projection terms can also be combined into a compound term that represents
an Object[] or Tuple. Listing 15 shows how to pack the result into an Object[]:

Listing 15. Shaping query result into an Object[]

CriteriaQuery<Object[]> q = cb.createQuery(Object[].class);
Root<Customer> c = q.from(Customer.class);
q.select(cb.array(c.get(Customer_.name), c.get(Customer_.age));
List<Object[]> result = em.createQuery(q).getResultList();

This query returns a result list in which each element is an Object[] of length 2, the zero-th
array element is Customer's name, and the first element is Customer's age.
Tuple is a JPA-defined interface to denote a row of data. A Tuple is conceptually a list
of TupleElements — whereTupleElement is the atomic unit and the root of all query
expressions. The values contained in a Tuple can be accessed by either a 0-based integer index
(similar to the familiar JDBC result), an alias name of the TupleElement, or directly by
theTupleElement. Listing 16 shows how to pack the result into a Tuple:

Listing 16. Shaping query result into Tuple

CriteriaQuery<Tuple> q = cb.createTupleQuery();
Root<Customer> c = q.from(Customer.class);
TupleElement<String> tname = c.get(Customer_.name).alias("name");
q.select(cb.tuple(tname, c.get(Customer_.age).alias("age");
List<Tuple> result = em.createQuery(q).getResultList();
String name = result.get(0).get(name);
String age = result.get(0).get(1);

Limitations on nesting
It is theoretically possible to compose complex result shapes by nesting terms such as
a Tuple whose elements themselves are Object[]s or Tuples. However, the JPA 2.0 specification
prohibits such nesting. The input terms of a multiselect() cannot be an array or tuple-valued
compound term. The only compound terms allowed as multiselect()arguments are ones created
by the construct()method (which essentially represent a single element).
However, OpenJPA does not put any restriction on nesting one compound selection term inside
another.

This query returns a result list each element of which is a Tuple. Each tuple, in turn, carries
two elements — accessible either by index or by the alias, if any, of the
individual TupleElements, or directly by the TupleElement. Two other noteworthy points
in Listing 16 are the use of alias(), which is a way to attach a name to any query expression
(creating a new copy as a side-effect), and acreateTupleQuery() method on QueryBuilder, which
is merely an alternative to createQuery(Tuple.class).

The behavior of these individual result-shaping methods and what is specified as the result
type argument of the CriteriaQuery during construction are combined into the semantics of
themultiselect() method. This method interprets its input terms based on the result type of
the CriteriaQuery to arrive at the shape of the result. To construct CustomerDetails instances
as in Listing 14 using multiselect(), you need to specify the CriteriaQueryto be of
type CustomerDetails and simply invoke multiselect()with the terms that will compose
the CustomerDetails constructor, as shown in Listing 17:
Listing 17. multiselect() interprets terms based on result type
CriteriaQuery<CustomerDetails> q = cb.createQuery(CustomerDetails.class);
Root<Customer> c = q.from(Customer.class);
q.multiselect(c.get(Customer_.name), c.get(Customer_.age));

Because the query result type is CustomerDetails, multiselect() interprets its argument
projection terms as the constructor argument to CustomerDetails. If the query were specified to
return a Tuple, the multiselect() method with the exact same arguments would
create Tuple instances instead, as shown in Listing 18:

Listing 18. Creating Tuple instances with multiselect()

CriteriaQuery<Tuple> q = cb.createTupleQuery();
Root<Customer> c = q.from(Customer.class);
q.multiselect(c.get(Customer_.name), c.get(Customer_.age));

The behavior of multiselect() gets more interesting with Object as result type or if no type
argument is specified. In such cases, if multiselect() is used with a single input term, then the
return value is the selected term itself. But if multiselect()contains more than one input term,
the result is an Object[].

Advanced features
So far, I have mainly emphasized the strongly typed nature of the Criteria API and the fact that
it helps to minimize syntactic errors that can creep into string-based JPQL queries. The
Criteria API is also a mechanism for building queries programmatically and so is often referred
to as a dynamic query API. The power of a programmable query construction API is limited only
by the inventiveness of its user. I'll present four examples:
x Using a weakly typed version of the API to build dynamic queries
x Using a database-supported function as a query expression to extend the grammar
x Editing a query for search-within-result functionality
x Query-by-example — a familiar pattern popularized by the object-database community

Weak typing and dynamic query building


The Criteria API's strong type checking is based on the availability of instantiated metamodel
classes at development time. However, for some use cases, the entities to be selected can only
be determined at run time. To support such usage, the Criteria API methods provide a parallel
version in which persistent attributes are referred by their names (similar to the Java
Reflection API) rather than by reference to instantiated static metamodel attributes. This
parallel version of the API can support truly dynamic query construction by sacrificing the type
checking at compile time. Listing 19 rewrites the example in Listing 6using the weakly typed
version:

Listing 19. Weakly typed query

Class<Account> cls = Class.forName("domain.Account");


Metamodel model = em.getMetamodel();
EntityType<Account> entity = model.entity(cls);
CriteriaQuery<Account> c = cb.createQuery(cls);
Root<Account> account = c.from(entity);
Path<Integer> balance = account.<Integer>get("balance");
c.where(cb.and
(cb.greaterThan(balance, 100),
cb.lessThan(balance), 200)));
The weakly typed API, however, cannot return correct generically typed expressions, thereby
generating a compiler warning for an unchecked cast. One way to get rid of these pesky
warning messages is to use a relatively rare facility of Java generics: parameterized method
invocation, as shown in Listing 19's invocation of the get() method to obtain a path expression.

Extensible datastore expressions


A distinct advantage of a dynamic query-construction mechanism is that the grammar is
extensible. For example, you can use the function() method in the QueryBuilder interface to
create an expression supported by the database:
<T> Expression<T> function(String name, Class<T> type, Expression<?>...args);

The function() method creates an expression of the given name and zero or more input
expressions. The function()expression evaluates to the given type. This allows an application to
create a query that evaluates a database function. For example, the MySQL database supports
a CURRENT_USER() function that returns the user-name and host-name combination as a
UTF-8 encoded string for the MySQL account that the server used to authenticate the current
client. An application can use theCURRENT_USER() function, which takes no argument, in
a CriteriaQuery, as Listing 20 demonstrates:

Listing 20. Using a database-specific function in a CriteriaQuery

CriteriaQuery<Tuple> q = cb.createTupleQuery();
Root<Customer> c = q.from(Customer.class);
Expression<String> currentUser =
cb.function("CURRENT_USER", String.class, (Expression<?>[])null);
q.multiselect(currentUser, c.get(Customer_.balanceOwed));

Notice that an equivalent query is simply not possible to express in JPQL, because it has a
defined grammar with a fixed number of supported expressions. A dynamic API is not strictly
limited by a fixed set of expressions.

Editable query
A CriteriaQuery can be edited programmatically. The clauses of the query — such as its
selection terms, the selection predicate in a WHERE clause, and ordering terms in an ORDER
BY clause — can all be mutated. This editing capability can be used in a typical "search-within-
result"-like facility whereby a query predicate is further refined in successive steps by adding
more restrictions.

The example in Listing 21 creates a query that orders its result by name and then edits the
query to order also by ZIP code:

Listing 21. Editing a CriteriaQuery

CriteriaQuery<Person> c = cb.createQuery(Person.class);
Root<Person> p = c.from(Person.class);
c.orderBy(cb.asc(p.get(Person_.name)));
List<Person> result = em.createQuery(c).getResultList();
// start editing
List<Order> orders = c.getOrderList();
List<Order> newOrders = new ArrayList<Order>(orders);
newOrders.add(cb.desc(p.get(Person_.zipcode)));
c.orderBy(newOrders);
List<Person> result2 = em.createQuery(c).getResultList();
In-memory evaluation in OpenJPA

With OpenJPA's extended features, the search-within-result example in Listing 21 can be made
even more efficient by evaluating the edited query in-memory. This example dictates that the
result of the edited query will be a strict subset of the original result. Because OpenJPA can
evaluate a query in-memory when a candidate collection is specified, the only modification
required is to the last line of Listing 21 to supply the result of the original query:

List<Person> result2 =
em.createQuery(c).setCandidateCollection(result).getResultList();

The setter methods on CriteriaQuery — select(), where(), ororderBy() — erase the previous
values and replace them with new arguments. The list returned by the corresponding getter
methods such as getOrderList() is not live — that is, adding or removing elements on the
returned list does not modify theCriteriaQuery; furthermore, some vendors may even return an
immutable list to prohibit inadvertent usage. So a good practice is to copy the returned list into
a new list before adding or removing new expressions.

Query-by-example
Another useful facility in a dynamic query API is that it can supportquery-by-example with
relative ease. Query-by-example (developed by IBM® Research in 1970) is often cited as an
early example of end-user usability for software. The idea of query-by-example is that instead
of specifying the exact predicates for a query, a template instance is presented. Given the
template instance, a conjunction of predicates — where each predicate is a comparison for a
nonnull, nondefault attribute value of the template instance — is created. Execution of this
query evaluates the predicate to find all instances that match the template instance. Query-by-
example was considered for inclusion in the JPA 2.0 specification but is not included. OpenJPA
supports this style of query through its extended OpenJPAQueryBuilder interface, as shown in
Listing 22:

Listing 22. Query-by-example using OpenJPA's extension of CriteriaQuery


CriteriaQuery<Employee> q = cb.createQuery(Employee.class);

Employee example = new Employee();


example.setSalary(10000);
example.setRating(1);
q.where(cb.qbe(q.from(Employee.class), example);
As this example shows, OpenJPA's extension of the QueryBuilder interface supports the
following expression:
public <T> Predicate qbe(From<?, T> from, T template);

This expression produces a conjunction of predicates based on the attribute values of the given
template instance. For example, this query will find all Employees with a salary of 10000 and
rating of 1. The comparison can be further controlled by specifying an optional list of attributes
to be excluded from comparison and the style of comparison for String-valued attributes.
(SeeResources for a link to the Javadoc for OpenJPA's CriteriaQuery extensions.)
Conclusion
This article has introduced the new Criteria API in JPA 2.0 as a mechanism for developing
dynamic, typesafe queries in the Java language. A CriteriaQuery is constructed at run time as
a tree of strongly typed query expressions whose use the article has illustrated with a series of
code examples.

This article also establishes the critical role of the new Metamodel API and shows how
instantiated metamodel classes enable the compiler to verify the correctness of the queries,
thereby avoiding run-time errors caused by syntactically incorrect JPQL queries. Besides
enforcing syntactic correctness, JPA 2.0's facilities for programmatic construction of queries
can lead to more powerful usage, such as query-by-example, using database functions, and —
I hope — many other innovative uses of these powerful new APIs that this article's readers will
devise.

Acknowledgments
I acknowledge Rainer Kwesi Schweigkoffer for his careful review of this article and valuable
suggestions, and fellow members of JPA 2.0 Expert Group for explaining the finer points of this
powerful API. I also thank Fay Wang for her contribution, and Larry Kestila and Jeremy Bauer
for their support during development of the Criteria API for OpenJPA.

  


 
   

   
 
 

 
  
  
! "##
$!% !#

    !"#$  #


%       
   # $   
     
 & '
( )
 *    +&,
 & # # 
 ,#-  #. 
 %/,0-1  2 !/,3
     
 %     1


' (! )

 !45
 "    #  67   
  
 ! # 895# ##
 8  ':';
 ,-
< 
 =>
 ?    @@

&

 +,&-./

 !A5
 ! #  B      
        

 '   1  
  ? !"
:&  !"
 %#C  
 ,-#  
 "   

*
  
! "##

1
 

 
 8 
 %

# 
  
D
   
 
 
 E 
 >00
00  00
 00 
 ?  :$ ?
%
,
& 
 ?.     ; ?
  

 " 
 % 
$  
  2 3

  
! "##

34
 

 
 ?#

# 
  
D
 ?#  
   
 F  7 : 
 !  
 "  & 
 &  
 *  0 #- 
   #0
0  0

2
5!  
!!$'
67#

@Entity
public class Person {
@Id protected String ssn;
protected String name;
protected Date birthDate;
. . .
@ElementCollection
protected Set<String> nickNames;
}

5!  
!!$'
67#

@Entity
public class Person {
@Id protected String ssn;
protected String name;
protected Date birthDate;
. . .
@ElementCollection
@CollectionTable(name=”ALIAS”)
protected Set<String> nickNames;
}

8
5!  
!!$1:)) 67#

@Embeddable public class Address {


String street;
String city;
String state;
. . .
}

@Entity public class RichPerson extends Person {


. . .
@ElementCollection
protected Set<Address> vacationHomes;
. . .
}

" 
#  !$1:))


@Embeddable public class ContactInfo {


@Embedded Address address;
. . .
}

@Entity public class Employee {


@Id int empId;
String name;
ContactInfo contactInfo;
. . .
}

-
1:)) 4
 
!
#

@Embeddable public class ContactInfo {


@Embedded Address address;
@OneToMany Set<Phone> phones;
. . .
}

@Entity public class Employee {


@Id int empId;
String name;
ContactInfo contactInfo;
. . .
}

--

))


@Entity public class CreditCard {


@Id long cardNumber;
@OneToOne Person cardHolder;
. . .
@OneToMany
@OrderColumn
List<CardTransaction> transactions;
}

-
"#

@Entity public class VideoStore {


@Id Integer storeId;
Address location;
. . .
@ElementCollection
Map<Movie, Integer> inventory;
}

@Entity public class Movie {


@Id String title;
@String director;
. . .
}

-&

 !:
#% 
!

 (: )( )

@Entity public class Order {


@Id int orderId;
. . .
@OneToMany(cascade=PERSIST, orphanRemoval=true)
Set<Item> lineItems;
. . .
}

-*
;7$ 

 &   


 *    
 >  # 
 &  
 *   '
  :#   
 > ;
 
#
#
 /
D
 /
 /
 * #1# 
   
1
'

-0

 
 < 7 

 %0  %/,0-1  


 % , ?
E>&
G< E
E>*!8H
>E= E8H
D
 /:     
 
 
 
 %   0 
 &  %/,  
 %     

% , ?C23
E>&>  >"F 
G< E  .IJKL954M

-2
 
 < 7 
34
 

 %# :    # 


 >   #
 ? 
 
#'
 E 
 ?0    #"F0'

-.

 <34#!

"F= +


N H
C,*
 FEH

?%
?>, %?
F*,,"
    

H!


   

-8
))


% , ?
E>&? ?   >"F  
G< E   <  IO =O
F="F= +23P45

-9

"#

" & P& 


"Q

% , ?  


N H23
C,* 23

E>&C %  >"F  


G< E N H23 ,"N OR<-RO
F=C,* 23Q5


51=#
!

*!=  
%   I
?%  
G< F4< F  S456
G< FA< F  S45A
 ,%   S5K6
 F=

-


) ! 7:!#
:

% , ?
E>& 
G< E H! 23"F;


5

 
34
 

 >$0  !"# 1


 =  !/, 
 %
 8  0 #  #   
 
 < # 
 %$0  0    
 /   

&

5

 >5!$ 

 ? 8 
 *  1

  
 
 ? /
 *   :1
 #

:
 8
8
 
D 
 E
 /
 
, 
&  
D
 # '$
 ! 
 F  # 
$
 
 %1

*
!4!'
)5

< 7






  






  !


 
  
"" !
#
" 
$"%    & &"

!
  
'(

"



"

 
  ! 
 
!

) 
 !  )

0

?
)
!
34
 

 ,  :-#8 C  2 %E9593


    # 
 !!
 !* 
 !E 
 C  0 (')
 *>
?,,8?N
F>F
 %   . # # 

2
,:# %

?  + %

! 
? ? ? 
%
!

>  ! 

8- =C= ?=

.

":!)

  ( 0 ) :#    


 
   
 
     
 &   &  23
 &  &  23
    .      
 *  0  1
 % #  # 

8
@
,
":!)

javac -processor
org.eclipse.persistence.internal.jpa.modelgen.CanonicalM
odelProcessor -sourcepath src -d src -classpath
/ace2_apps/eclipselink/jlib/eclipselink.jar:.:/ace2_apps
/eclipselink/jlib/JPA/javax.persistence_2.0.0.v200911271
158.jar -proc:only
-Aeclipselink.persistencexml=src/META-
INF/persistence.xml src/demo/*.java
Note: Creating the metadata factory …
Note: Building metadata class for round element:
demo.Item
. . .

http://weblogs.java.net/blog/lancea/archive/2009/12/15/generating-jpa-20-static-metamodel-classes-using-eclipselink-20-and-n

9

1
75 
* "  +  

 "
 &,+
  
 "
 &,+
  -
 "
 &,+
     
 "
 &,+
  . "
 "
 &,/ 

0
  "
1
0-  -
0    2
 

0. " / .

"



3

&
":!) 5 
* "  +  

 "
 &,+""4 
 
 "
 &,+
    " / 2
 
 "
 &,+
    " /
2
 
 "
 &,+
    " /  " 

04 
 5 )* $62 78 " "  4 
"9
0/  " "

  "
: 1
  ," /
2
 "
%- 
-
  ," /
2
 "
%2



  ," / 2
 "
%.

"



3

&-

5!  7

 ! 
 %0 -
 ,0:-
 !    #:     
   #     
 >(-)     
 "   
     
 !     ::   
 '-23       

&

:

! (

34
 

 ! 
 F -
 ! #
 E 
 
     -#
 ! # 
 
 !   -23
 ,- 
 ! %%"&"%"?TE =U   -
 ! %%"&"%"?TGE" U ' -
 ! %%"&"%"?T>E? T"F?E & FU  

&&

! (
 

 &   ;-


#
#
 / / ;,-& 
<
 F  /  ;-& 

 $ '-
 $ '-

 !,- '2#   -3


 ,- '2#  -3

&*
5 
5!$
 
!
34
 

 &  ' 


(# ) 
      
  #   
 :   
 &   0  
 F :     
 !A5   .  0  


&0

,))5!$
 
! !#


 $ '$   
 $ '$ 
 $ '$ 
 $ '$  :
 

&2
, ::7!$ 34 

 &#'   


 '   >E # 
   !1  
 ? !"
 &  !"
 !-
 %#  
 %   . # # 

&.


  


 
   

   
 
 
EXCEPTIONS IN JPA
javax.ejb.EJBException: javax.persistence.PersistenceException:
org.hibernate.PersistentObjectException: detached entity passed to persist:

javax.ejb.EJBException: javax.persistence.PersistenceException:
org.hibernate.PersistentObjectException: detached entity passed to persist:

You are trying to persist an entity which has the same id as another entity which is already
exist at the PersitanceContet - This is confusing :-).

What you should do is try to merge or reload the entity from the DB:

...
@PersistenceContext(unitName = "myDB")
private EntityManager manager;
...

publicv void....{
...
manager.merge(entity)
...
}

OR

...
@PersistenceContext(unitName = "myDB")
private EntityManager manager;
...

publicv void....{
...
manager.find(YourEntity.class, youEntityInstance.getId());
manager.persist(yourEntityInstance);
...
}
Loading an Image into a database using JPA

Loading an image (or any file) into a database via JPA is quite easy actually, here is some code
to help you out. Please note that this is quick dirty code, and you might consider a lot of
changes were you to use it. But the idea is there, and will allow you see how it goes.
Firstly one needs to create their entity class
01 @Entity
02 public class ImageExample implements Serializable {
03 @Id
04 @GeneratedValue(strategy = GenerationType.AUTO)
05 private Long id;
06
private String MimeType; // Useful to store the mime type incase you want to send it
07
back via a servlet.
08
09 // We mark up the byte array with a long object datatype, setting the fetch type to lazy.
10 @Lob
@Basic(fetch=FetchType.LAZY) // this gets ignored anyway, but it is recommended for
11
blobs
12 protected byte[] imageFile;
Using a simple bit of Java code taken from the Java Developers Almanac, we read the file and
return it as a byte array.

01 public byte[] readImageOldWay(File file) throws IOException


02 {
Logger.getLogger(Main.class.getName()).log(Level.INFO, "[Open File] " +
03
file.getAbsolutePath());
04 InputStream is = new FileInputStream(file);
05 // Get the size of the file
06 long length = file.length();
07 // You cannot create an array using a long type.
08 // It needs to be an int type.
09 // Before converting to an int type, check
10 // to ensure that file is not larger than Integer.MAX_VALUE.
11 if (length > Integer.MAX_VALUE)
12 {
13 // File is too large
14 }
15 // Create the byte array to hold the data
16 byte[] bytes = new byte[(int) length];
17 // Read in the bytes
18 int offset = 0;
19 int numRead = 0;
20 while (offset < bytes.length && (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0)
21 {
22 offset += numRead;
23 }
24 // Ensure all the bytes have been read in
25 if (offset < bytes.length)
26 {
27 throw new IOException("Could not completely read file " + file.getName());
28 }
29 // Close the input stream and return bytes
30 is.close();
31 return bytes;
32 }
We create an entity object and use the entity manager.

01 /*
02 * Put a JPG image into the db
03 */
04 ImageExample myExample = new ImageExample();
05 myExample.setMimeType("image/jpg");
06 file = new File("images/mushroom.jpg");
07 try
08 {
09 // Lets open an image file
10 myExample.setImageFile(mainCourse.readImageOldWay(file));
11 }
12 catch (IOException ex)
13 {
14 Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
15 }
Then we persist the entity object.

1 fatController.create(myExample);
This works easily as well for PDF documents
view source
print?
01 /*
02 * Put a PDF into the db
03 */
04 ImageExample myExampleTwo = new ImageExample();
myExampleTwo.setMimeType("application/pdf")
05
;
06 file = new File("images/studentexample.pdf");
07 try
08 {
09 // Lets open an image file
10 Logger.getLogger(Main.class.getName()).log(Level.INFO, "[Call Read]");
11 myExampleTwo.setImageFile(mainCourse.readImageOldWay(file));
12 Logger.getLogger(Main.class.getName()).log(Level.INFO, "[Property set]");
13 }
14 catch (IOException ex)
15 {
16 Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex);
17 }
18 fatController.create(myExampleTwo);
Logger.getLogger(Main.class.getName()).log(Level.INFO, "The number of objects is : " +
19
fatController.getImageExampleCount());
You can easily prove that the JPA objects were persisted to the database by reading the objects
back from the database.

01 /*
02 * Lets read the images from JPA, and output them to the filesystem
03 */
04 // Get the list of images stored in the database.
05 List<ImageExample> images = fatController.findImageExampleEntities();
06 File outfile = null;
07 // Go through the list returned, looking for PDF/JPG files.
08 for (int i = 0; i < images.size(); i++)
09 {
10 if (images.get(i).getMimeType().equalsIgnoreCase("application/pdf"))
11 {
12 // write out the pdf file
13 outfile = new File("out/test"+images.get(i).getId()+".pdf");
14 try
15 {
16 mainCourse.writeFile(outfile, images.get(i).getImageFile());
17 }
18 catch (IOException e)
19 {
20 Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, e);
21 }
22 }
23 else if (images.get(i).getMimeType().equalsIgnoreCase("image/jpg"))
24 {
25 // write out th
he pdf file
26 ou
utfile = new File("out/tes
F st"+images.g
get(i).getId()+ ".jpg");
27 try
y
28 {
29 mainCourse.
m writeFile(ou
utfile, images
s.get(i).getIm
mageFile());
30 }
31 caatch (IOExcep
ption e)
32 {
33 Logger.getLog
L me()).log(Levell.SEVERE, n
gger(Main.cllass.getNam null, e);
34 }
35 }
36 e
else
37 {
38 ogger.getLogg
Lo ger(Main.cla
ass.getName()).log(Level.S
SEVERE, "U
Unknown file
e type");
39 }
40 }

If you are
e wondering
g what code I used to write it to a filee, it was sim
mple like this
s.

c void writeF
01 public File(File file, byte[] data) throws IOE
Exception
02 {
03 OuttputStream fo
f = new File
eOutputStre
eam(file);
04 // Write
W the da
ata
05 fo.w
write(data);
06 // flush
f the file
e (down the toilet)
t
07 fo.fllush();
08 // Close
C the do
oor to keep th
he smell in.
09 fo.close();
10 }
e, if you werre to use this
Of course s in producttion you wou uld add morre error chec cking, and
probably
y follow some e better bestt practices. I have also sskipped a lott of steps, as
ssuming youu
know whhat you are doing
d
JPA 2.0 Concu
urrency a
and lockin
ng
Optimisttic Concurrrency
Optimistic locking leets concurren nt transactio
ons process simultaneously, but de etects and
prevent collisions,
c th
his works best for appliccations wherre most conccurrent tran nsactions do not
conflict. JPA
J Optimis stic locking allows
a anyonne to read a
and update a an entity, ho
owever a vers sion
check is made upon commit and d an exceptioon is thrown
n if the versiion was updated in the
database e since the entity was read. In JPA for Optimisttic locking you annotate e an attributte
with @Ve ersion as shoown below:

public cla
ass Employe ee {
@ID innt id;
@Version n int version
n;

The Verssion attributee will be incremented with a successsful committ. The Versio
on attribute can
be an intt, short, long
g, or timesta
amp. This re
esults in SQ
QL like the fo
ollowing:

E Employee SET ..., vers


“UPDATE sion = versiion + 1
WHER ND version = readVersion”
RE id = ? AN

The advaantages of op ptimistic locking are tha


at no databa
ase locks aree held whichh can give be etter
scalabilitty. The disad
dvantages arre that the user
u or appliication mustt refresh and
d retry failed
d
updates.

Optimisttic Locking g Example


In the op
ptimistic lock
king example below, 2 concurrent trransactions are updatin ng employee e1.
The transaction on the left comm using the e1
mits first cau 1 version attrribute to be incremented
with the update. The e transaction
n on the righht throws an
n OptimisticLLockExceptiion because the
e1 versio
on attribute is an when e1 was read, c ausing the ttransaction to roll back..
i higher tha
Additional Locking with JPA Entity Locking APIs
With JPA it is possible to lock an entity, this allows you to control when, where and which kind
of locking to use. JPA 1.0 only supported Optimistic read or Optimistic write locking. JPA 2.0
supports Optimistic and Pessimistic locking, this is layered on top of @Version checking
described above.

JPA 2.0 LockMode values :

x OPTIMISTIC (JPA 1.0 READ):


o perform a version check on locked Entity before commit, throw an
OptimisticLockException if Entity version mismatch.
x OPTIMISTIC_FORCE_INCREMENT (JPA 1.0 WRITE)
o perform a version check on locked Entity before commit, throw an
OptimisticLockException if Entity version mismatch, force an increment to the
version at the end of the transaction, even if the entity is not modified.

x PESSIMISTIC:
o lock the database row when reading
x PESSIMISTIC_FORCE_INCREMENT
o lock the database row when reading, force an increment to the version at the
end of the transaction, even if the entity is not modified.

There are multiple APIs to specify locking an Entity:


x EntityManager methods: lock, find, refresh
x Query methods: setLockMode
x NamedQuery annotation: lockMode element

OPTIMISTIC (READ) LockMode Example


In the optimistic locking example below, transaction1 on the left updates the department
name for dep , which causes dep's version attribute to be incremented. Transaction2 on the
right gives an employee a raise if he's in the "Eng" department. Version checking on the
employee attribute would not throw an exception in this example since it was the dep Version
attribute that was updated in transaction1. In this example the employee change should not
commit if the department was changed after reading, so an OPTIMISTIC lock is used
: em.lock(dep, OPTIMISTIC). This will cause a version check on the dep Entity before
committing transaction2 which will throw an OptimisticLockException because
the dep version attribute is higher than when dep was read, causing the transaction to roll
back.
OPTIMIS STIC_FORCE E_INCREME ENT (write) LockMode Example
In the OPPTIMISTIC_F FORCE_INCREMENT loc cking examp ple below, trransaction2 on the right
wants to be sure thaat the dep na
ame does no ot change duuring the tra
ansaction, so
o transaction n2
e dep Entity em.lock(de
locks the ep, OPTIMIS STIC_FORCE E_INCREME ENT) and thhen calls
em.flush uses dep's ve
h() which cau ersion attribbute to be in cremented iin the database. This wiill
cause an pdates to de
ny parallel up ep to throw an OptimistticLockExceeption and ro oll back. In
mit time when the dep veersion attrib
transactiion1 on the left at comm bute is checkked and foun nd to
be stale, an OptimistticLockExcepption is thro
own
Pessimis
stic Concurrrency

Pessimistic concurreency locks thhe database row when d data is read, this is the e
equivalent off a
(SELECTT . . . FOR UPPDATE [NOW WAIT]) . Pesssimistic lock king ensurees that trans sactions do n
not
update thhe same enttity at the sa
ame time, wh hich can simmplify appliccation code, but it limits
concurre
ent access too the data wh hich can cau use bad scallability and may cause d deadlocks.
Pessimistic locking is
s better for applications
a s with a high her risk of co
ontention am mong concurrrent
transactiions.
The exam
mples below show:
1. re
eading an enntity and the en locking itt later
2. re
eading an enntity with a lock
l
3. re
eading an enntity, then laater refreshinng it with a lock

The Trad
de-offs are thhe longer you u hold the lo
ock the greaater the riskss of bad scallability and
deadlock
ks. The later you lock the e risk of stalle data, whicch can then cause an
e greater the
optimistiic lock excep
ption, if the entity
e was updated
u afterr reading bu
ut before lockking.

The rightt locking app


proach depe
ends on yourr application
n:

x what
w is the riisk of risk off contention among conccurrent tran
nsactions?
x What
W are the requiremen nts for scalabbility?
x What
W are the requiremen nts for user re-trying
r on failure?
JPA Perrformance, Don't Ignorre the Datab base
JPA Perfformance, Don't
D Ignoree the Datab base
Database e Schema
Good Da atabase schema design is s important for perform ance. One oof the most b
basic
optimizattions is to design your tables
t to take as little sp
pace on the d
disk as poss
sible , this m
makes
disk read
ds faster and d uses less memory
m for query
q processsing.

Data Typ pes


You shou uld use the smallest
s datta types poss
sible, especiially for indeexed fields. T
The smaller y your
data typees, the more
e indexes (an
nd data) can fit into a bloock of memo ory, the fastter your querries
will be.

Normaliz zation
Database e Normalizattion eliminattes redundaant data, whiich usually makes upda ates faster siince
there is less
l data to change.
c Howwever a Normmalized scheema causes joins for que eries, whichh
makes qu ueries sloweer, denormallization spee
eds retrieval.. More normmalized schem mas are bettter
for applic
cations involving many transactions
t s, less norm
malized are beetter for reporting typess of
applications. You sh hould norma alize your sc
chema first, tthen de-norrmalize later. Applicatio ons
often neeed to mix thee approachees, for exampple use a parrtially norm
malized schemma, and
duplicatee, or cache, selected colu
umns from one
o table in another tab ble. With JPAA O/R mapp ping
you can use
u the @Em mbedded annotation for denormaliz ed columns to specify a persistent ffield
whose @Embeddable e type can bee stored as an
a intrinsic part of the oowning entitty and share e the
identity of
o the entity.
Databasee Normalizaation and Mapping
M Inhheritance Hiiearchies
The Class Inheritanc
ce hierarchy shown belo
ow will be ussed as an exa
ample of JPA
A O/R mapp
ping.

In the Sin
ngle table peer class mappping shown n below, all cclasses in th
he hierarchy are mapped d to a
single tab
ble in the da
atabase. This table has a discrimina ator column (mapped
by @Disc criminatorC Column), wh hich identifie
es the subclaass. Advanttages: This iis fast for
queryingg, no joins arre required. Disadvantag ges: wastagge of space since all inheerited fields are
in every row,
r a deep inheritance hierarchy will
w result in wide tables with many,, some emptty
columns.

oined Subcla
In the Jo ass mappingg shown belo ow, the root of the class hierarchy iss represented by
a single table,
t and eaach subclass
s has a sepaarate table th
hat only conntains those fields specific to
that subcclass. This is normalized
d (eliminatess redundantt data) whichh is better fo
or storage an
nd
updates. However qu ueries cause joins whichh makes queeries slower eespecially foor deep
hierachiees, polymorpphic queries and relation
nships.
In the Ta
able per Classs mapping (in JPA 2.0, optional in JPA 1.0), evvery concre ete class is
mapped to a table inn the databas se and all th
he inherited state is repeeated in tha
at table. This
s is
not normmlalized, inhe
erited data is
i repeated which
w wastees space. Qu ueries for En
ntities of the
e
same typpe are fast, however
h polyymorphic qu ueries causee unions whiich are slow wer.

Know wh hat SQL is executed


e
You needd to understand the SQL L queries you ur applicatio
on makes an nd evaluate their
performa
ance. Its a go
ood idea to enable
e SQL logging,
l thenn go throughh a use casee scenario to
o
check the executed SQL.
S Loggin
ng is not parrt of the JPA
A specificatio
on, With EcliipseLink youu
can enab
ble logging of SQL by settting the following propeerty in the peersistence.x
xml file:

<propertiies>
<propeerty name="eclipselink.llogging.level" value="FIN
NE"/>
</properrties>

bernate you set


With Hib s the follow
wing propertty in the perrsistence.xm
ml file:

<propertiies>
<propeerty name="hibernate.sh
how_sql" vallue="true" />
>
</properrties>
Basically
y you want too make yourr queries acc cess less datta, is your a
application rretrieving mo
ore
data than
n it needs, are
a queries accessing
a too
o many rowss or columns? Is the dattabase query y
analyzing
g more rows s than it needs? Watch out
o for the fo ollowing:
x qu ueries which
h execute too often to reetrieve needeed data
x re etrieving moore data thann needed
x qu ueries which
h are too slo
ow
o you ca an use EXPL LAIN to see where
w you sshould add in ndexes

With MySSQL you can


n use the slo
ow query log g to see whicch queries arre executing
g slowly, or y
you
can use the
t MySQL query
q analyzzer to see slo
ow queries, query execuution counts s, and resultts of
EXPLAINN statements
s.

Understaanding EXP PLAIN


For slow queries, you
u can preced de a SELECTT statement with the keeyword EXPL LAIN to get
informatiion about th
he query execution plan,, which expllains how it would proce
ess the
SELECT,, including information about how tables are jo oined and in
n which ordeer. This helps
find miss
sing indexess early in the
e developmen
nt process.

You shou
uld index columns that are frequenttly used in Q
Query WHER RE, GROUP BY clauses, and
columns frequently used
u in joins
s, but be aw
ware that ind
dexes can slo
ow down ins
serts and
updates.

Lazy Loaading and JPA


J
With JPAA many-to-on ne and man ny-to-many relationships
r s lazy load b
by default, m
meaning they y will
be loadedd when the entity
e in the
e relationship
p is accessedd. Lazy loadding is usuallly good, butt if
you needd to access all
a of the "ma any" objects in a relation
nship, it willl cause n+1 selects where n
is the nu
umber of "maany" objects.
You can change the relationship
p to be loaded eagerly ass follows :

However you should be careful with


w eager lo
oading which
h could causse SELECT s statements tthat
fetch too much data.. It can caus
se a Cartesia
an product i f you eagerly
y load entitiies with seve
eral
related collections.

ant to overrid
If you wa de the LAZY
Y fetch type for
f specific u
use cases, yo
ou can use F
Fetch Join. F
For
example this query would
w eagerlly load the employee adddresses:

In Generral you should lazily load


d relationshiips, test you
ur use case sscenarios, ch
heck the SQ
QL
log, and use @NameQ Queries with h JOIN FETC CH to eagerlly load when n needed.
Partitionning
the mainn goal of parttitioning is to
t reduce thee amount off data read fo
for particularr SQL opera
ations
so that th
he overall re
esponse time e is reduced

Vertical Partitioninng splits tab


bles with ma
any columnss into multipple tables witth fewer
columns, so that onlly certain columns are in
ncluded in a particular dataset, witth each partiition
g all rows.
including

Horizonttal Partitionning segmen nts table row


ws so that diistinct groupps of physica al row-basedd
datasets are formed. All columns s defined to a table are ffound in eacch set of parrtitions. An
example of horizonta al partitionin
ng might be a table that contains hiistorical data a being
partitioned by date.

Vertical Partitionin
ng

xample of verrtical partitio


In the ex oning below
w a table thatt contains a number of vvery wide te
ext or
BLOB co olumns that aren't refere i split into two tables w
enced often is with the mosst referenced
d
columns in one tablee and the seldom-referen nced text or BLOB colum mns in anotther.

By removving the larg


ge data colum
mns from th
he table, youu get a fasterr query response time fo
or the
more freq
quently acceessed Custommer data. Wide
W tables caan slow dow wn queries, sso you shoulld
always en
nsure that all
a columns defined
d to a table are acctually needeed.
The exam
mple below shows
s the JP
PA mapping for the tablees above. Thhe Customerr data table with
the more
e frequently accessed an nd smaller da
ata types iss mapped to the Custom mer Entity, th
he
CustomeerInfo table with
w the less
s frequently accessed annd larger datta types is m
mapped to thhe
CustomeerInfo Entity with a lazily
y loaded one
e to one rela
ationship to tthe Custome er.
Horizonttal Partition
ning
The majo
or forms of horizontal
h pa
artitioning are
a by Rangee, Hash, Hassh Key, List, and Compo
osite.

Horizontaal partitionin
ng can make e queries fasster becausee the query ooptimizer kn nows what
partitions contain thhe data that will satisfy a particular query and w will access oonly those
necessarry partitions during querry execution n. Horizontall Partitioningg works best for large
databasee Applicationns that conta
ain a lot of query
q activity
y that targetts specific ra
anges of
databasee tables.

Hibernatte Shards
Partitioning data horrizontally intto "Shards" is used by g
google, linked
din, and oth
hers to give
extreme scalability fo
or very largee amounts off data. eBayy "shards" daata horizonta
ally along its
s
primary access
a path.

Hibernatte Shards is a frameworkk that is des


signed to enccapsulate su
upport for horizontal
partitioning into the Hibernate Core.
C
Caching
JPA Leveel 2 caching avoids datab
base access for already loaded entitties, this maake reading
reading frequently
f acccessed unm
modified entiities faster, h
however it ccan give bad scalability ffor
frequent or concurreently updated entities.

You shou uld configuree L2 cachingg for entities


s that are:
x re ead often
x modified
m infre
equently
x Not
N critical iff stale
You shou uld also conffigure L2 (ve
endor specifiic) caching ffor maxElem
ments, time tto expire,
refresh....

JP
PA Caching

JPA Leve
el 1 caching
g

JPA has 2 levels of caching. The first level off caching is the persisteence context.

The JPA Entity Mana


ager maintaiins a set of Managed
M En
ntities in thee Persistence
e Context.
The Entitty Manager guarantees that within a single Perssistence Con ntext, for an
ny particularr
databasee row, there will be only one object instance. Ho
owever the saame entity ccould be
managedd in another User's trans saction, so you
y should uuse either op
ptimistic or pessimistic
locking as
a explainedd in JPA 2.0 Concurrenc cy and lockin
ng

The code
e below showws that a find
d on a mana
aged entity w
with the sam
me id and cla
ass as anoth
her in
the same
e persistence
e context , will
w return thhe same insttance.

@Stateles
ss public Sh
hoppingCartB
Bean implem
ments Shopp
pingCart {

@PersisttenceContex
xt EntityMan
nager entityM
Manager;

public OrderLine
O creeateOrderLinne(Product product,Ord
p der order) {
OrdderLine orderLine = new OrderLine(o order, produ
uct);
entiityManager.p erLine); //M
persist(orde Managed
OrdderLine orde erLine2 =enttityManager.find(OrderLLine,
orderLin ne.getId()));
(ordeerLine == orrderLine2) // TRUE
retu
urn (orderLin ne);
}

}
The diagrram below shows
s the liffe cycle of an
n Entity in reelation to th
he Persistentt Context.

The code n Entity. A rreference to a container managed


e below illusttrates the liffe cycle of an
EntityMaanager is injected using the persiste ence contextt annotation. A new orde er entity is
created and
a the entitty has the sttate of new. Persist is ca alled, makin ng this a man
naged entity y.
because it is a statelless session bean it is by y default usiing containeer managed transactions s,
when thiis transactioon commits , the order is s made pers istent in thee database. W When the
orderline
e entity is retturned at th
he end of the e transactionn it is a deta
ached entity..

The Persistence Context can be either


e Transsaction Scop ontext 'lives' for
ped-- the Perrsistence Co
the lengtth of the tran
nsaction, or Extended-- the Persisteence Contextt spans mulltiple
transactiions. With a Transaction n scoped Perrsistence Co
ontext, Entities are "Deta
ached" at thhe
end of a transaction..
As shownn below, to persist
p the changes
c on a detached eentity, you ca
all the EntittyManager's
merge() operation,
o which returns s an updatedd managed eentity, the e ntity updatees will be
persisted
d to the data
abase at the end of the trransaction.

An Extennded Persiste
ence Contexxt spans multiple transaactions, and the set of E
Entities in th
he
Persisten
nce Context stay Manage ed. This can
n be useful in
n a work flow
w scenario wwhere a
"conversa
ation" with a user spans
s multiple re
equests.
The code e below showws an examp ple of a State eful Session EJB with an n Extended Persistence
Context ini a use case scenario to o add line Ittems to an O
Order. After tthe Order is persisted in
n the
createOrder method,, it remains managed un ntil the EJB remove metthod is called. In the
addLineItem method d , the Orderr Entity can be updated because it iis managed, and the upd dates
will be pe
ersisted at th
he end of th
he transactio on.

The exam mple below contrasts


c uppdating the Order
O using a transactio on scoped Pe
ersistence
Context verses
v an ex
xtended Pers
sistence conttext. With th
he transactioon scoped persistence
context, an Entity Manager find must be don ne to look u
up the Order, this returnns a Manage ed
Entity wh hich can be updated. With the Extended Persisttence Conteext the find iis not necesssary.
The perfoormance adv vantage of not
n doing a database
d rea
ad to look upp the Entity, must be
weighed against the disadvantag ges of memory consump ption for cach
hing, and th
he risk of cac
ched
entities being
b update
ed by anotheer transactio
on. Dependiing on the a application a
and the risk of
contentioon among co oncurrent tra
ansactions this
t may or may not give better perfformance /
scalabilitty.
JPA seco
ond level (L
L2) caching

ond level (L2) caching sh


JPA seco hares entity state
s acrosss various perrsistence con
ntexts.

JPA 1.0 did


d not spec cify support of a second level cache, however, m
most of the persistence
providers
s provided su
upport for second level cache(s).
c PA 2.0 speciffies support for basic ca
JP ache
operation
ns with the new
n Cache API,
A which is
s accessible from the En
ntityManage erFactory, shhown
below:
If L2 cachhing is enab
bled, entities
s not found in
i persistencce context, w
will be loade
ed from L2 ca
ache,
if found.

The adva
antages of L22 caching arre:
x av voids databaase access fo
or already lo
oaded entitiees
x faaster for read
ding frequen
ntly accessedd unmodifieed entities

The disad
dvantages of L2 caching g are:
x memory
m conssumption forr large amou unt of objectts
x Stale data forr updated ob bjects
x Concurrency
C for write (op
ptimistic lock exception,, or pessimisstic lock)
x Bad
B scalabilitty for frequeent or concurrently upda ated entitiess

uld configure
You shou e L2 caching
g for entities
s that are:
x reead often
x modified
m infre
equently
x Not
N critical iff stale

uld protect any


You shou a data tha at can be con ncurrently m
modified with h a locking s
strategy:
x Must
M handle optimistic lo ock failures on flush/coommit
x coonfigure exppiration, refrresh policy to
o minimize llock failuress

The Querry cache is useful


u for qu
ueries that are uently with tthe same parameters, fo
a run frequ or not
modified tables.
The EcliipseLink JP
PA persisten
nce providerr caching A
Architecture
e

The EcliipseLink cac


ching Archite
ecture is sho
own below.

Support for second level cache in n EclipseLin


nk is turned on by defau
ult, entities rread are L2
cached. You
Y can disaable the L2 cache.
c EclipseLink cach
hes entities iin L2, Hibernnate caches
n L2. You can configure caching by E
entity id and state in Entity type o or Persisten
nce Unit withh the
followingg configuration paramete ers:

x Cache
C isolatio
on, type, sizze, expiration
n, coordinatiion, invalida
ation,refresh
hing
x Coordination
C (cluster-me essaging)
x Messaging:
M JMS, RMI, RM MI-IIOP, …
x Mode:
M SYNC, SYNC+NEW W, INVALIDA ATE, NONE

The exam
mple below shows
s config
guring the L2
2 cache for a
an entity using the @Ca
ache annotattion
The Hibe
ernate JPA persistence
e provider caching
c Arc
chitecture

The Hibeernate JPA persistence


p provider
p cach
hing architeecture is diffe
ferent than E
EclipseLink: it is
not confiigured by de s not cache enities just id and statee, and you ca
efault, it does an plug in
different L2 caches. The
T diagram m below showws the differrent L2 cachhe types thatt you can plu
ug
into Hibeernate.

The confi
figuration of the cache depends
d on the
t type of ca aching plugged in. The example bellow
shows co
onfiguring th
he hibernatee L2 cache fo using the @Cache anno
or an entity u otation
Best Practices: Testing JPA

Greetings all.

I have set up a structure for creating some JPA entities. I am using spring, hibernate entity
manager, maven and derby to create a 'test environment' and everything seems to work. I can
create an 'AbstractJpaTests' subclass and run unit tests with the entity manager to my heart's
content.

What I am wrestling with, is the best practices for doing these kind of tests. It seems that
writing tests of CRUD operations against every JPA entity that I create is a very tedious
approach. I have also considered creating an abstract subclass of AbstractJpaTests which
templates the basic CRUD tests and uses abstract methods as factories, so that new JPA tests
can be created by creating concrete subclasses and implementing these basic abstract
methods. This starts to get a little problematic when dealing with relationships and complex
object graphs though.

I have also had it suggested to me that there is no need to write unit tests of CRUD operations
on JPA entities as any problems will be found when doing the higher level tests of business
methods and that testing against an embedded derby instance will not always mean the
entities will work in other RDMS setups.

I am curious about how others approach this subject. Is everyone writing CRUD tests for each
of thier entities? Do you have some better approach? Are you testing them at this level at all?

JPA implementation patterns: Testing

What to test?

The first question to ask is: what code do we want to test? Two kinds of objects are involved
when we talk about JPA: domain objects and data access objects (DAO's). In theory your
domain objects are not tied to JPA (they're POJO's, right?), so you can test their functionality
without a JPA provider. Nothing interesting to discuss about that here. But in practice your
domain objects will at least be annotated with JPA annotations and might also include some
code to manage bidirectional associations (lazily), primary keys, or serialized objects. Now
things are becoming more interesting...

(Even though such JPA specific code violates the POJO-ness of the domain objects, it needs to be
there to make the domain objects always function the same way. Whether inside or outside of a
JPA container. The managing of bidirectional associations and using UUIDs as primary keys are
nice examples of this. In any case, this is code you most certainly need to test.)

Of course, we'd also need to test the DAO's, right? An interesting question pops up here: why
do we want to test the DAO's? Most of them just delegate to the JPA provider and testing the
JPA provider makes no sense unless we are writing "learning tests" (see also Robert Martin's
Clean Code) or developing our own JPA provider. But the combination of the DAO's and the
JPA specific part of the domain objects is testworthy.
What to test agains
st?

Now thatt we know what


w to test, we can decide what to ttest against. Since we arre testing
databasee code, we want
w our testt fixture to in
nclude a dattabase. Thatt database can be an
embedde ed in-memorry database such as HSQ QLDB (in meemory-only m mode) or a ""real" databa
ase
such as MySQL
M or Oracle.
O Using g an embedd ded databasee has the bigg advantage of being eassy to
set up; th
here is no neeed for everyyone runnin ng the tests tto have a run
nning MySQ QL or Oracle
instance. But if yourr production n code runs against
a anotther databasse, you mighht not catch all
databasee issues this way. So an integration test againstt a real datab base is also needed, butt
more on that later.

For mostt tests we ne eed more tha an just the database.


d Wee need to se t it up corre
ectly before a test
and afterr the test we e need leave it in a usablle state for tthe next testt to run. Setting up the
schema and
a filling th
he database with the rig ght data befoore running the test are not that hard to
do (a.k.a. left as an exercise
e for the
t reader atabase to a usable state
), but returrning the da e
after the test is a mo ore difficult problem.
p I've
e found a nu umber of app proaches to this problem m:

x The Spring Frramework in ncludes the a test frameework that u uses transactions to man nage
thhe state of your test fixtuure. If you annotate
a youur test to be @Transactio onal, the
SpringJUnit4 4ClassRunne er will start a transactio on before eacch test startts and roll ba ack
thhat transacttion at the en nd of the tesst to return tto a known sstate. If you u are still usiing
JUnit 3.8 you u can extend d the AbstractTransactio onalSpringC ContextTests s base class for
thhe same effe ect. This migght seem nic ce but in pra actice I've fouund this method to be
unsatisfactor
u ry for a nummber of reasons:
1. By default the JPA A context is not flushed d until the trransaction is s committed or a
query y is executedd. So unless your test inccludes a queery, any mod difications aare
not ac ctually propaagated to the database w which can h hide problemms with invallid
mappings and such. You cou uld try and ex xplicitly invo
oke EntityMManager.flush h
beforee the end of the test, butt then the teests don't re present reall scenario's
anymore.
2. Also, saving
s an enntity and theen retrieving g it in the saame session does not
uncov ver those nas sty lazy loadding issues. You're probably not eve en hitting the
database as the JPAJ providerr will return a reference to the objec ct that you juust
saved!
3. Finally, in a test you
y might likke to first sttore some da ata in the da
atabase, then n
run th he tests, andd finally checck that the rright data w was written oout to the
database. To test this properlly you need three separa ate transacttions without the
wo transactiions being ro
first tw olled back.
x Iff you use an embedded in-memory
i database
d thaat database will be clean n when you run
thhe first test and
a you won n't need to worry
w about leaving it in n a good statte after all th
he
teests are run. This means you will no ot have to rooll back any transaction ns and can h have
multiple
m tran
nsactions witthin one testt. But you m might have to o do someth hing special
between each h test. For exxample, whe en using thee Spring TesttContext fra amework you u can
use
u the @DirttiesContext annotation to t reinitializze the in-mem mory databa ase between
teests.
x Iff you cannott use an in-m memory data abase or re-iinitializing itt after everyy test is too
ex xpensive, yoou can try an nd clear all the
t tables affter every tesst (or before every test). For
ex xample, DbU Unit can be used to dele ete all data fr
from your test tables or truncate all test
taables. Foreiggn key contrraints may get in the way ay though, so o you will waant to
teemporarily disable
d refere
ential integrrity before peerforming th hese operatio ons.
At what scope to test?

The next thing is to decide on the scope of the tests. Will you write small unit tests, larger
component tests, or full-scale integration tests? Because of the way JPA works (the leakiness of
its abstraction if you will), some problems might only surface in a larger context. While testing
the persist method on DAO in isolation is useful if you want to know whether the basics are
correct, you will need to test in a larger scope to shake out those lazy loading or transaction
handling bugs. To really test your system you will need to combine small unit tests with larger
component tests where you wire your service facades with the DAOs under test. You can use
an in-memory databases for both tests. And to complete your test coverage you will need an
integration test with the database to be used in production using a tool such a Fitnesse.
Because we are not specifically testing the JPA code in that case, having unit tests on a smaller
scale will help you pinpoint DAO bugs more quickly.

What to assert?

One final thing to tackle is what to assert in the tests. It might be that your domain objects are
mapped to an existing schema in which case you want to make sure that the mapping is
correct. In this case you would like to use raw JDBC access to the underlying database to
assert that the right modifications were made to the right tables. But if the schema is
automatically generated from the JPA mapping you probably will not care about the actual
schema. You'll want to assert that persisted objects can be correctly retrieved in a new session.
Direct access to the underlying schema with JDBC is not necessary and would only make such
test code brittle.

I'm pretty sure that I have not covered all test scenarios in this blog because testing database
code is a very complicated area. I would love to hear how you test your database code, whether
it uses JPA or some other persistency mechanism.
JPA Best Practices

Accessing a database is THE most common task in any IT application. Using one single layer
which is more readable, manageable, and maintainable for all apps becomes a real need. JPAis
the right step towards that.
We can also see that other technologies are emerging and taking advantage of the ease of
embedding annotations in entities. Be aware not to make your entities too “heavy”. Too heavy
means, less manageable and difficult to reused.

Writing entities with JPA is easy but, if not implemented with love and care it is also might be a
real time bomb in terms of performance, once data amounts grow in the persistence layer (e.g
tables in the db are getting really big).
Here are some JPA best practices and issues that one should take in mind from the
very beginning of creating entites:
First, you can enable logging of actual SQL being generated by the JPA implementation. Check
your environment configuration in order to do that. There are always surprises and this is a
good place to start understanding what is going on.

1. Try to avoid joins on tables:

x Merge tables (look for one to one relations).


x Divide tables in order to lazy fetching potentially large fields (Blob data for example, lots of
text).
x Use Inheritance strategy with single table and @DiscriminatorColumn.
x Prefer Lazy fetch type when possible.
2. Use prepared statements in your JPQL (e.g select e from Entity e where e.id = :someId). This
will enable compiled statement caching.

3. Don’t start a transaction for read operations.

4. Use Named Queries when possible. Named queries can be annotated with query hints.

5. Understand Caching in order to reduce DB round trips:

x There are three levels of caching available by JPA providers: Transaction level (think as single
transaction cache), Extended Persistence Context (think as single client caching) and
Persistence Unit Cahce (think as application level caching). The later caching needs a caching
provider which support this kind of caching.
x There is another provider specific caching feature - read only entities caching , once marked
they will be loaded to the persistence unit and will stay there.
4. Don’t order if not needed.

5. Create indexes in tables.

6. Use bulk JPQL statements instead of iterating single operations.

7. Know JPA defaults. This will help you in maintain you entities which might grow to great
number.

x For example, the default fetch type for many to one relation is EAGER. Is it always needed/not
performance issue?
8. Use cascade property carefully or unnecessary SQL operation will be executed.

9. Validate your connection pool configuration against you application requirements.

10. Consider enabling optimistic locking on an entity.


Conclusion
Performance issues are a common ongoing task and most of the times a pretty difficult to
track. mostly due to time limitations leading to fast development and no time to redesign. You
find your self grab what you can in this area or sit until white smoke comes out of a real
performance issue pops up. I hope knowing or just be aware of the above issues will help you
in implementing a stable, maintainable and performance aware domain model.
Hibernate/JPA best practices

Override hashCode() and equals()


The Hibernate reference states that "It is recommended that you implement equals() and
hashCode() to compare the natural key properties of the entity."
The reason is simple: different instances of the class may represent the same record in the
database. Therefore, when comparing these two instances, you'd like to get equal result, while
default equals implementation will return not-equal since it's not the same instance.

This becomes really important, when working with collections, especially with Sets. You don't
want the same object to appear twice in set, right?

Overriding the hashCode() and equals() is not a very complex goal, but you must be very
careful:
1. Remember that two equal objects must return the same hash code. Therefore, you cannot
use auto-generated Hibernate id in hashCode() - this value is not assigned for the newly
created objects. After persistence occurs, the value is assigned, so the hashCode will change,
when the object actually wasn't changed!
2. Changing the fields that participate in hashCode() will change the hash code value. So if
your object is stored in a Set (or it's key of a Map), you won't be able to retrieve it from the set
anymore - one hash was used for insert and another one was used for retrieve.
So basically you'll need to remember not to change objects that are stored in sets! And this is
really important!
So you may ask: how will I know who stored my object in a set?
My answer is simple: you cannot know this, unless you don't give your objects out. So you are
the only person who is using these objects, so you know how they are kept, right?
Storing the objects without giving them out is not so weird idea: keep the persistence layer
away from the business logic and return a copy of object when required.
Another option: return immutable objects to the business tier. So the business tier won't be
able to change them. When the change is required - provide a special API. Thus the objects
won't change accidentally.

Try to Make All Object Immutable


This may sound weird, how exactly the persistent objects can be immutable. But in the
previous part I described why it's important. And actually it can be quite easily achieved:
1. Make all setters private. Thus it will be impossible to call them without using reflection.
(Hibernate will use reflection and populate the properties during the object retrieval)
2. When returning collections, wrap them with Collections.unmodifiable. So the user won't be
able to modify your collections.
3. Allow changes only via special methods.

Return Copy of Persistent Objects to the Business Tier


So no accidental change in hash code may occur.
Additionally when filling the business objects, a lot of potential problems may be resolved.
Consider that the persistent object contains a lazy collection. If the object is returned as is to
the business tier, the lazy elements in the collections can be accessed after the transaction was
closed, therefore the query to the database will fail and user will get an exception.

h3. Change Data in Collections Only via Special Methods


When having associations, take care of this association via special method: for example, Parent
class will have method addChild(Child child).
When returning the values of collections wrap them using Collections.unmodifiable to prevent
accidental changes.
This is useful both to handle bidirectional associations correctly and to prevent accidental
changes in hash code.
Summary
1. Override hashCode() and equals() of the entities using the natural key properties of the
entity.
2. Don't compare auto-generated id in hashCode().
3. Don't change the properties that participate in the hashCode() for objects stored in
collections that use hash code (especially Sets or Maps). If such a change must occur, reinsert
object into collection. Remember that remove must occur before the property is updated.
4. Keep the persistence tier away from the business logic as much as possible. Don't pass the
persistence objects to the business at all.
5. Make your objects immutable (or semi-immutable): make all setters private, return collection
values only wrapped with Collections.unmodifiable, make changes in collections only via
special methods.
JPA/Hibernate best practices?

Hi, I'm new to ORM. I spent a couple days trying to figure it out and I've got some basic stuff
working (JPA, annotations, selecting and persisting using native query and jpa query
language). Now i want to start designing an approach for my application, so I have some
questions related to best practices for JPA.

1. All of my data access is done through DAO objects. I have a baseDAO superclass where in
that constructor I create an instance of a protected EntityManager member object and that
manager doesn't ever get .close()'d until the finalize() method of my BaseDAO.

Is that ok? Or would it be better to have each method of the DAO call the factory to
create/close() a new EntityManager just for the life of the method?

2. Is there a way to detach an Entity from being auto-updated in the database without calling
the persist() method? I have a feeling this relates to my manager not being .close()'d until the
DAO gets garbage collected...I'd like to be able to change some of my Entity objects database
values for display without having the change saved in the db.

3. Let's say I have an Entity with 10 members. I want to do a quick lookup and i'm only going
to use 2 of those members for display. What's the best way to tell jpa/hibernate to select and
build that entity object with only the data I care about?

Hopefully my questions make sense. if you guys have any links to common JPA practices,
that'd be great too.

Thanks,
Aaron


Enterprise JPA & Spring 3.0 - Tips and Tricks for JEE Persistence

As with many technologies, the basics are easy. The hard part comes when the developer needs
to do sophisticated integration, development, and testing as part of an enterprise application. A
large enterprise application requires the developer to think of issues that affect the
development, scalability and robustness of the application. This presentation will cover the
advanced topics described below with a focus on the new persistence features in Spring 3.0
and JPA 2.0.

A large enterprise application often will have several sub-projects that each contain their own
JPA persistence unit. This opens up a number of questions around how to organize the
persistence units and how the code between sub-projects should interoperate. Developers will
gain insight into these issues and will see a couple of solutions using live code examples.

Many enterprise applications require integration with an application server's JTA mechanism.
JTA integration allows for JPA components to work with container managed transactions and
distributed transactions. A typical usage scenario for JPA & JTA is this: read from a database
using JPA, perform some business logic, put a message on a queue, write to the database
(again using JPA). A JTA transaction allows you to ensure that the entire set of operations is
committed or a rollback is performed. In this presentation, the developer will understand the
limitations and configuration of using JTA and JPA together ? primarily through real code
examples.

Once unit tests are written, developers often gloss over doing fine-grained integration testing
just for their persistence layer. Integration testing with JPA means simply one thing: running
your JPA components against your target database, for example, Oracle. Overlooking this
aspect leads to problems being discovered later in the test cycle (UAT for example) and makes it
more difficult to find and fix bugs. This presentation will use live code examples to explain a
strategy for getting integration testing for free by reusing unit tests.

Using optimistic locking versus pessimistic locking seems clear cut to most developers.
However, a full understanding of the issues with using pessimistic, or datastore, locking is
required before making this decision. Developers will get information in the trade offs when
using strategy or the other, and how these strategies can be used together with the same
persistence unit.











JPA in Java SE
December 22nd, 2009
Using JPA on top of the persistence layer makes things much more manageable and
maintainable. In EE apps this fact makes a real difference.

Implementing a domain model via objects is another step towards modeling the business. Now
days, you will find that more services are available at the entities level. Entities fields can be
marked with validation rules (J2EE 6 Beans validation) . Also indexing on top of Lucene is
made easy with Hibernate Search (JBoss project).

All these services should be free from any container restrictions and so they are.

I will show a very basic implementation of JPA in Java SE using eclipseLink implementation.

Folder structure

-org.jpa.test
--Test.class
--User.class
-META-INF
--MANIFEST.MF
--persistence.xml
Entity Mapped to a table in the DB.

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.Table;
/**
* The persistent class for the users database table.
*
*/
@Entity
@Table(name = "users")
public class User implements Serializable {
private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private String id;
@Column(name = "Name")
private String name;
@Column(name = "Zip")
private String zip;
@Column(name = "Address")
private String address;
public User() {
}
public String getId() {
return this.id;
}
public void setId(String id) {
this.id = id;
}
public String getName() {
return this.name;
}
public void setName(String name) {
this.name = name;
}
public String getZip() {
return this.zip;
}
public void setZip(String zip) {
this.zip = zip;
}
public String getAddress() {
return address;
}
public void setAddress(String address) {
this.address = address;
}
}
MANIFEST.MF
Manifest-Version: 1.0
Class-Path:
persistence.xml

<?xml version="1.0" encoding="UTF-8"?>


<persistence version="1.0"
xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence
http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd">
<persistence-unit name="SimpleJPA5">
<class>com.jpa.test.User</class>
<properties>
<property name="eclipselink.jdbc.user" value="root" />
<property name="eclipselink.jdbc.password" value="roded75" />
<property name="eclipselink.jdbc.url" value="jdbc:mysql://localhost:3306/test" />
<property name="eclipselink.jdbc.driver" value="com.mysql.jdbc.Driver" />
<property name="eclipselink.ddl-generation" value="drop-and-create-tables" />
</properties>
</persistence-unit>
</persistence>

Java SE Client
import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
public class Test {
/**
* @param args
*/
public static void main(String[] args) {
User aUser = new User();

aUser.setName(”John John”);
aUser.setZip(”123456);
aUser.setAddress(”CA sun blvrd”);
EntityManagerFactory emf = Persistence.createEntityManagerFactory(”SimpleJPA5);

EntityManager em = emf.createEntityManager();

em.getTransaction().begin();
em.persist(aUser);
em.getTransaction().commit();
em.close();
emf.close();
System.out.println(”Done”);

}
}
Author:adminCategories:Common Java, JPATags:J2SE, JPA
Simple Time Out Wrapper
December 1st, 2009

A simple time out wrapper can be achieved in the following way:

//Set a timer to throw interruption when timeout


Timer timer = new Timer();
timer.schedule(new InterruptScheduler(Thread.currentThread()), timeOutValueInMillis);
try
{
//Your code Here...
} catch (InterruptedException e)
{
//Interruption Occured - Handle...
}
finally
{
// Stop the timer
timer.cancel();
}
Author:adminCategories:Common JavaTags:J2SE, Timeout, Timer
Monitoring Java Process (for example JBoss)
August 9th, 2009
No comments
Since JDK 1.5 a monitoring tool is available. JConsole.exe resides under jdk/bin.
In order to use it just use the following vm argument when running a java process (jboss,
yourJar.jar, …):

Just add the vm argument: -Dcom.sun.management.jmxremote

for example: in JBoss run.bat add the following line:

rem Run with managed VM in order to allow Monitoring via JMX

set JAVA_OPTS=%JAVA_OPTS% -Dcom.sun.management.jmxremote

In order to identify the Java process of the Jboss started use:

the jps utility (Also resides under jdk/bin): jps -l

Example outpout:

4384 org.jboss.Main

2172

3644 sun.tools.jps.Jps

3456 Tray

Author:adminCategories:Common Java, MonitoringTags:JBOSS, JConsole, JPS, Monitoring


Read Text File with Java
July 13th, 2009
No comments
Read a Text File with java BufferedReader class

public static void main(String[] args) throws Exception {

String filePath = "c:\\temp\aTextFile.txt";


try {
BufferedReader input = new BufferedReader(new
FileReader(filePath));
try {
String line = null;
while ((line = input.readLine()) != null) {
if (line != null) {
handleLine(line);
}
}
} finally {
input.close();
}
} catch (Exception e) {
e.printStackTrace()
}
}

Author:adminCategories:Common JavaTags:java
Iterating Lists Complexity Issues
March 17th, 2009
No comments
Iterating a list in order to find a specific item is a pretty common task.

Lets take the following code example:

Problem:
Lets say we have the following example:

import java.util.Vector;

public class CodeReview {


public static void main(String[] args) {
Vector items = new Vector();
Vector itemsToBeRemoved = new Vector();

items.add("A");
items.add("B");
items.add("C");

itemsToBeRemoved.add("B");

new CodeReview().removeItems(items, itemsToBeRemoved);


System.out.println(items);

private void removeItems(Vector items, Vector itemsToBeRemoved) {


for (Object anItem : itemsToBeRemoved) {
//Remove or if not exist will keep unchanged
items.remove(anItem);
}
}
}

This simple code hides a performance issue which might not be noticed while implementing
business logic under a stressed deadline.
Why? Lets assume we have list1 with n items and list2 with m items. The complexity of finding
an item will be n*m = n^2. This might be innocent in some cases or a total disaster in other
cases.
Solution:
The first thing comes in mind is to use some sort of a Map and this is the correct.

As the cost of at least n complexity will be “paid”, instead of keep on using the
remove method (with n complexity) at each iteration (leading n*m complexity) a conversion of
the list to a Map (initially or while iterating) instance will optimize the complexity
into complexity of n . If we will use for example a LinkedHashSet the complexity then will be
n*1 using the item as key.
This is a very simple solution that might optimize performance, in some cases even
dramatically.

Summary:
while using any the method contains or remove an algorithm with n complexity is used. This
might make iterations and sub interations very expensive. Where memory is not an issue keep
in mind the conversion to Map instance when you can.



Rela
ationship
ps






Concurrency (Locking) Mode
OC4J also provides concurrency modes for handling resource contention and parallel execution
within EJB 3.0 entities and EJB 2.1 entity beans with container-managed persistence.

Entity beans with bean-managed persistence manage the resource locking within the bean
implementation themselves.

Concurrency modes include the following:

x Optimistic Locking: Multiple users have read access to the data. When a user attempts
to make a change, the application checks a version field (also known as a write-lock
field) to ensure the data has not changed since the user read the data.

When optimistic locking is enabled, TopLink caches the value of this version field as it
reads an object from the data source. When the client attempts to write the object,
TopLink compares the cached version value with the current version value in the data
source in the following way:

x If the values are the same, TopLink updates the version field in the object and
commits the changes to the data source.
x If the values are different, the write operation is disallowed because another
client must have updated the object since this client initially read it.
x Pessimistic Locking: The first user, who accesses the data with the purpose of updating
it, locks the data until completing the update. This manages resource contention and
does not allow parallel execution. Only one user at a time is allowed to execute the
entity bean at a single time.
x Read-only: Multiple users can execute the entity bean in parallel. The container does
not allow any updates to the bean's state.

These concurrency modes are defined for each bean and apply on the transaction boundaries.

By default, in EJB 3.0, the JPA persistence manager assumes that the application is
responsible for data consistency. Oracle recommends that you use the @Version annotation to
specify a version field and enable JPA-managed optimistic locking.
JPA Ex
xceptions
s

Goals fo
or Exceptio
on Handlin
ng

x An
A application exception thrown
t by an
a enterprisee bean insta ance should be reported to
th
he client PRE
ECISELY (i.ee., the clientt gets the SAAME exceptio on).
x An
A application exception thrown
t by an
a enterprisee bean insta ance should NOT
au
utomaticallyy rollback a client's tran
nsaction unleess the appllication exce eption was
defined to cau
use transacttion rollbackk. The clientt should typiically be giveen a chance to
ecover a tran
re nsaction fromm an applica ation excepttion.
x An
A unexpecte ed exceptionn that may have
h left the instance's sstate variable
es and/or
underlying
u pe
ersistent datta in an incoonsistent staate can be hhandled safelly.


Message-driven Beans

Let's now look at the final type of EJB: message-driven beans.

Business interface
The business interface of a message-driven bean (MDB) is the message-listener interface that is
determined by the messaging type in use for the bean. The interface
is javax.jms.MessageListener. The message-driven bean must implement the appropriate
message listener interface for the messaging type that the message-driven bean supports or
must designate its message-listener interface using the@MessageDriven annotation or the
deployment descriptor.

Bean class
In EJB 3.0, the MDB bean class is annotated with the @MessageDriven annotation, which
specifies the message queue this MDB monitors (such as queue/mdb).

The bean class needs to implement the MessageListener interface, which defines only one
method, onMessage(). When a message arrives in the queue monitored by this MDB, the
container calls the bean class's onMessage() method and passes the incoming message in as
the call parameter.

In our example, the TraderBean.onMessage() method retrieves the message body, parses out
the parameters, performs the trade, and saves the result to a static data manager class. The
"sent" timestamp on the service request message serves as the unique ID for the calculation
record (it works well for low-volume Web sites). A check.jsp JSP page picks up and displays the
calculation record based on the message ID:

@MessageDriven(activateConfig =
{
@ActivationConfigProperty(propertyName="destinationType",
propertyValue="javax.jms.Queue"),
@ActivationConfigProperty(propertyName="destination",
propertyValue="queue/mdb")
})
public class TraderBean implements MessageListener {

public void onMessage (Message msg) {


try {
TextMessage tmsg = (TextMessage) msg;
Timestamp sent =
new Timestamp(tmsg.getLongProperty("sent"));
StringTokenizer st =
new StringTokenizer(tmsg.getText(), ",");

buy ("SNPS",1000);

RecordManager.addRecord (sent, "BUY SUCCESSFUL");

} catch (Exception e) {
e.printStackTrace ();
}
}
// ... ...
}
Sending a message
To use th he message-driven bean n, the client (such
( as thee JSP page, ttrader.jsp, in
n this case) uses
the stand dard JMS AP PI to obtain the target message
m queu ue to the MD
DB by way o of the queue
name (qu ueue/mdb), and then it sends the message
m to th
he queue:
try {
InitialContext ctx = new InitialCContext();
queue = (Queue) ctx x.lookup("quueue/mdb");;
QueueC ConnectionFFactory factoory =
(QueueConnection nFactory) ctxx.lookup("CoonnectionFaactory");
cnn = faactory.create
eQueueConn nection();
sess = cnn.createQu
c ueueSession n(
fa
alse,QueueSession.AUTO O_ACKNOWL LEDGE);
} catch (EException e) {
e.printtStackTrace ();
}
TextMess sage msg = sess.createT
s TextMessage("SNPS",100 00);
sender = sess.createS Sender(queu ue);
sender.se end(msg);

Callbackks for messa age-driven beans


b
The follow
wing life cyc
cle event calllbacks are supported forr message-d
driven beans
s:
x PostConstruc ct
x PreDestroy

Message Service Configurat


C tion Options

Impleme
enting an EJB 3.0 MDB
B

Configurring an EJB
B 3.0 MDB to Access a Message Se
ervice Proviider Using J
J2CA

Configurring an EJB
B 3.0 MDB to Access a Message Se
ervice Proviider Directly
y

Configurring Parallel Message Processing


P
Configuring Maximum Delivery Count

Configuring Connection Failure Recovery for an EJB 3.0 MDB

Configuring a Life Cycle Callback Interceptor Method on an EJB 3.0 MDB

Using Annotations
You can specify an EJB 3.0 message-driven bean class method as a life cycle callback method
using any of the following annotations:
x @PostConstruct
x @PreDestroy

Configuring a Life Cycle Callback Interceptor Method on an Interceptor Class of an EJB


3.0 MDB

Using Annotations
You can specify an interceptor class method as an EJB 3.0 message-driven bean life cycle
callback method using any of the following annotations:
x @PostConstruct
x @PreDestroy

Configuring an Around Invoke Interceptor Method on an EJB 3.0 MDB

Configuring an Around Invoke Interceptor Method on an Interceptor Class of an EJB 3.0


MDB

Configuring an Interceptor Class for an EJB 3.0 MDB

Configuring OC4J-Proprietary Deployment Options on an EJB 3.0 MDB

Understanding Message Services

A message service provider is responsible for providing a destination to which clients can send
messages and from which message-driven beans can receive messages for processing.

OC4J supports a variety of message service providers for both XA-enabled two-phase commit
(2PC) and non-XA enabled transactions.

You can access a message service provider directly or by way of a J2EE Connector Architecture
(J2CA) resource adapter such as Oracle JMS Connector.

You can use JNDI to look up and retrieve these components using the following:

x JNDI initial context


x EJB context
x EJB 3.0 annotations and resource injection
Understanding EJB Timer Services
You can set up a timer that invokes a timeout callback method at a specified time, after a
specified elapsed time, or at specified intervals.
Note:
Timers apply to all EJB types except stateful session beans and EJB 3.0 entities.

For EJB 3.0 applications, using the @Timeout annotation, you can annotate any EJB method
as the timeout callback method.

For EJB 2.1 applications, your EJB must implement the TimedObject interface and provide a
timeout callback method namedejbTimeout.

Timers are for use in modeling of application-level processes, not for real-time events.

OC4J provides standard Java EE timers as well as a convenient Java EE timer extension that
allows configuration similar to the Unix cron utility.

Timer and timeout callback methods should be called within a transaction. OC4J supports
transaction attribute REQUIRES_NEW for timeout callbacks. For more information on
transaction attributes, see "How are Transactions Handled When a Client Invokes a Business
Method?").

An enterprise bean accesses EJB timer services by means of dependency injection, through
the EJBContext interface, or through lookup in the JNDI namespace.

Understanding Java EE Timer Services


The EJB timer service is a container-managed service you use to define callback methods on
your EJB that are scheduled for time-based events. The EJB timer service provides a reliable
and transactional notification service for timed events. Timer notifications may be scheduled to
occur at a specific time, after a specific elapsed duration, or at specific recurring intervals. You
can define callback methods on your EJB to receive these time-based events. The Java EE
timer service is implemented by OC4J

Understanding OC4J Cron Timer Services


In UNIX, you can schedule a cron timer to execute regularly at specified intervals. Oracle has
extended OC4J to support cron timers with EJB. You can use cron expressions for scheduling
timer events with EJB deployed to OC4J. Using an OC4J cron timer, you can create timers that
invoke a timeout callback method or any arbitrary Java class's main method.

Understanding EJB Data Source Services


{
Managed Data Source
Native Data Source
}




Who Manages a Transaction?
A transaction can be managed by either the container or the bean
Container-managed transaction management is the default.

When configuring transaction management for your enterprise beans, consider the following
restrictions:

x EJB 3.0 entities cannot be configured with a transaction management type. EJB 3.0
entities execute within the transactional context of the caller.
x EJB 2.1 entity beans must always use container-managed transaction demarcation. An
EJB 2.1 entity bean must not be designated with bean-managed transaction
demarcation.

For all other EJB types, you can choose either container-managed or bean-managed
transaction management.

What are Container-Managed Transactions?


When you use container-managed transactions (CMT), your EJB delegates to the container the
responsibility to ensure that a transaction is started and committed when appropriate.
All session and message-driven beans may use CMT.

EJB 2.1 entity beans must use CMT.

EJB 3.0 entities cannot be configured with a transaction management type. EJB 3.0 entities
execute within the transactional context of the caller.

When developing an enterprise bean that uses CMT, consider the following:

x Do not use resource manager-specific transaction management methods such


as java.sqlConnection methods commit,setAutoCommit,
and rollback or javax.jms.Session methods commit or rollback.
x Do not obtain or use the javax.transaction.UserTransaction interface.
x A stateful session bean using CMT may implement
the javax.ejb.SessionSynchronization interface.
x An enterprise bean that uses CMT may
use javax.ejb.EJBContext methods setRollbackOnly and getRollbackOnly.

For an EJB that uses CMT, for each business method, you can also specify a transaction
attribute that determines how the container manages transactions when a client invokes the
method.




What are Bean-Managed Transactions?
When you use bean-managed transactions (BMT), the bean-provider is responsible for ensuring
that a transaction is started and committed when appropriate.

Only session and message-driven beans may use BMT.

When developing an EJB that uses BMT, consider the following:


x Use the javax.transaction.UserTransaction methods begin and commit to demarcate
transactions.

x A stateful session bean instance may, but is not required to, commit a started
transaction before a business method returns.
If a transaction has not been completed by the end of a business method, the container
retains the association between the transaction and the instance across multiple client
calls until the instance eventually completes the transaction.

x A stateless session bean instance must commit any transactions that it started before a
business method or timeout callback method returns.

x A message-driven bean instance must commit a transaction before a message listener


method or timeout callback method returns.

x After starting a transaction, do not use resource-manager specific transaction


management methods such as java.sqlConnectionmethods commit, setAutoCommit,
and rollback or javax.jms.Session methods commit or rollback.
x A bean that uses BMT must not
use EJBContext methods getRollbackOnly and setRollbackOnly. It must
useUserTransaction method getStatus and rollback instead.

How are Transactions Handled When a Client Invokes a Business Method?

For an enterprise bean that uses CMT (see "What are Container-Managed Transactions?"), you
can specify a transaction attribute that determines how the container must manage
transactions when a client invokes a bean method.

You can specify a transaction attribute for each of the following types of bean method:

x a method of a bean's business interface;


x a message listener method of a message-driven bean;
x a timeout callback method;
x a stateless session bean's Web service endpoint method;
x for EJB 2.1 and earlier, a method of a session or entity bean's home or component
interface

Table 2-6 shows what transaction (if any) an EJB method invocation uses depending on how
its transaction attribute is configured and whether or not a client-controlled transaction exists
at the time the method is invoked.

OC4J starts a container-controlled transaction implicitly to satisfy the transaction attribute


configuration when a bean method is invoked in the absence of a client-controlled transaction.
Table 2--6 EJB Tran
nsaction Su
upport by Tr
ransaction Attribute

Transacttion Cliient-Contro
olled
Attribute
e Client-Cont
C rolled Transaction Exiists Traansaction D
Does Not Ex
xist

Not Supp
ported Container
C su
uspends the client transsaction Use no transac
ction
Supports
s Use
U client-co
ontrolled tra
ansaction Use no transac
ction
Required
dFoot 1 Use
U client-co
ontrolled tra
ansaction Container starrts a new
tra
ansaction
Requires New Container
C su
uspends the client transsaction Container starrts a new
and
a starts a new transac
ction tra
ansaction
Mandatory Use
U client-co
ontrolled tra
ansaction Excception raised
Never Exception
E ra
aised Use no transac
ction

How do You Particiipate in a Global


G or Tw
wo-Phase Co
ommit (2PC
C) Transactiion?
If all reso
ources enlistted in a tran
nsaction are XA-complia ant, then OC
C4J automattically
coordina ates a global or two-phas se commit trransaction.

The midd
dle-tier coord
dinator supp
ports the folllowing:

x an
ny XA-comp pliant resourrce;
x in
nterpositioniing and tran
nsaction inflo
ow;
x la
ast resource commit opttimization;
x re
ecovery loggiing;

Understtanding EJ
JB Security
y Services
You can configure yo
our EJB to use
u the Java a EE securityy services th
hat OC4J pro
ovides, inclu
uding
the follow
wing:
x Java 2 Security Model;
x Java Authenttication and Authorization Service (J
JAAS);
Exceptions from a Session Bean's Business Interface Methods

x Table below specifies how the container must handle the exceptions thrown by the
methods of the business interface for beans with container-managed transaction (CMT)
demarcation, including the exceptions thrown by business method interceptor methods
which intercept the invocation of business methods. The table specifies the container's
action as a function of the condition under which the business interface method
executes and the exception thrown by the method. The table also illustrates the
exception that the client will receive and how the client can recover from the exception.

Table 10.1. Handling of Exceptions Thrown by a Business Interface Method of a Bean with
Container-Managed Transaction Demarcation
Method
Method condition Container's action Client's view
exception

Receives Application Exception.


Re-throw Application Can attempt to continue
Exception. computation in the transaction,
Mark the transaction and eventually commit the
Application
for rollback if the transaction unless the application
Exception
application exception exception is specified as causing
is specified as causing rollback (the commit would fail if
rollback. the instance
called setRollbackOnly).

Log the exception or


error (so that the
System Administrator
is alerted of the
Bean method runs in problem).
the context of the
caller's transaction. Mark the transaction
The caller can be for rollback.
another enterprise
bean or an arbitrary
Discard instance (so
client program.
that the container
This case may happen
must not invoke any
withRequired,Mandator Receivesjavax.ejb.EJBTransaction
business methods or
y, all other RolledbackException.
container callbacks on
andSupportsattributes. exceptions the instance).
Continuing transaction is fruitless.
Throwjavax.ejb.EJBTra
nsactionRolledbackExc
eption to client. If the
business interface is a
remote business
interface that
extends java.rmi.Remo
te,
thejavax.transaction.Tr
ansactionRolledbackEx
ceptionis thrown to the
client, which will
Method
Method condition Container's action Client's view
exception

receive this exception.

If the instance
called setRollbackOnly(
), then rollback the
transaction, and re-
throw Application
Exception.
Receives Application Exception.
Mark the transaction
for rollback if the
Application application exception If the client executes in a
Exception is specified as causing transaction, the client's
rollback, and then re- transaction is NOT marked for
throw Application rollback, and client can continue
Exception. its work.
Bean method runs in
the context of a Otherwise, attempt to
transaction that the commit the
container started transaction, and then
immediately before re-throw Application
dispatching the Exception.
business method.
Log the exception or
This case may happen error.
withRequired andRequi
resNewattributes. Rollback the container-
started transaction.

Discard instance. Receives EJBException.

all other Throw EJBException t If the client executes in a


exceptions o client. If the business transaction, the client's
interface is a remote transaction may or may not be
business interface that marked for rollback.
extendsjava.rmi.Remot
e,
the java.rmi.RemoteEx
ception is thrown to
the client, which will
receive this exception.

Bean method runs with Receives Application Exception.


an unspecified
transaction context. If the client executes in a
Application Re-throw Application
Exception Exception. transaction, the client's
This case may happen transaction is NOT marked for
with with rollback, and client can continue
theNotSupported,Never its work.
Method
Method condition Container's action Client's view
exception

, Log the exception or


andSupportsattributes. error.

Discard instance.
Receives EJBException.
Throw EJBException t
all other o client. If the business If the client executes in a
exceptions interface is a remote transaction, the client's
business interface that transaction may OR may not be
extendsjava.rmi.Remot marked for rollback.
e,
the java.rmi.RemoteEx
ception is thrown to
the client, which will
receive this exception.

x Table below specifies how the container must handle the exceptions thrown by the
methods of the business interface for beans with bean-managed transaction (BMT)
demarcation, including the exceptions thrown by business method interceptor methods
which intercept the invocation of business methods. The table specifies the container's
action as a function of the condition under which the business interface method
executes and the exception thrown by the method. The table also illustrates the
exception that the client will receive and how the client can recover from the exception.

Table 10.2. Handling of Exceptions Thrown by a Business Interface Method of a Session


Bean with Bean-Managed Transaction Demarcation
Bean
Bean method
method Container action Client receives
exception
condition

Application Re-throw Application


Receives Application Exception.
Exception Exception.

Log the exception or error.

Mark for rollback a transaction


Bean is that has been started, but not
stateful or yet completed, by the instance.
stateless
session. all other Discard instance.
Receives EJBException.
exceptions
Throw EJBException to client.
If the business interface is a
remote business interface that
extendsjava.rmi.Remote,
thejava.rmi.RemoteException is
thrown to the client, which will
receive this exception.
Exceptions from Message-Driven Bean Message Listener Methods

x Table below specifies how the container must handle the exceptions thrown by a
message listener method of a message-driven bean with container-managed transaction
(CMT) demarcation, including the exceptions thrown by business method interceptor
methods which intercept the invocation of message listener methods. The table specifies
the container's action as a function of the condition under which the method executes
and the exception thrown by the method.

Table 10.3. Handling of Exceptions Thrown by a Message Listener Method of a Message-


Driven Bean with Container-Managed Transaction Demarcation
Method condition Method exception Container's action

If the instance called setRollbackOnly,


rollback the transaction and re-throw
Application Exception
Application Exception to resource
adapter.
Mark the transaction
for rollback if the
Otherwise, attempt to commit the
application exception
transaction unless the application
is specified as causing
exception is specified as causing
rollback.
Bean method runs in the rollback and re-throw Application
context of a transaction that Exception to resource adapter.
the container started
immediately before Log the exception or error (so that the
dispatching the method. System Administrator is alerted of the
problem).
This case happens with
the Required attribute. Rollback the container-started
transaction.
system exceptions
Discard instance (so that the container
must not invoke any methods on the
instance).

Throw EJBException that wraps the


original exception to resource adapter.

Re-throw Application Exception to


Application Exception
resource adapter.
Bean method runs with an
unspecified transaction Log the exception or error.
context.
Discard instance.
This case happens with system exceptions
the NotSupportedattribute.
Throw EJBException that wraps the
original exception to resource adapter.

x Table below specifies how the container must handle the exceptions thrown by a
message listener method of a message-driven bean with bean-managed transaction
(BMT) demarcation. The table specifies the container's action as a function of the
condition under which the method executes and the exception thrown by the method.
Table 10
0.4. Handlin
ng of Excepttions Thrown by a Mess
sage Listene
er Method off a Message
e-
Driven Bean
B with Be
ean-Manage ed Transactiion Demarcaation

Bean method
m Bean metthod
Contain
ner action
condiition exceptio
on

Ap
pplication Ex
xception Re-throw App
plication Excception to re
esource adap
pter.

Lo
og the excep
ption or error.

Bean is Mark
M for rollb
back a transsaction that has been
message--driven sttarted, but nnot yet comppleted, by th
he instance.
bean system excepttions
Discard insta
ance.

Th
hrow EJBEx xception thaat wraps the original
ex
xception to rresource adaapter.

javax.ejb
b.SessionSy
ynchronizatiion Interface


Begin tran
nsaction sequ
uence:

Commit transaction se
equence:
UML Diiagram DB Design

 

Potrebbero piacerti anche