Professional Documents
Culture Documents
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.
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.
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.
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.
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.
@Stateless
{
@Tx(TxType.REQUIRED)
@MethodPermission({"customer"})
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.
{
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:
The following code will add the callback listener AccountListener to the Account Bean:
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.
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.
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:
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):
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.
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:
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.
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 {
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.
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.
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.
@Stateful
public class TraderBean implements Trader, Serializable {
} catch (Exception e) {
e.printStackTrace ();
}
}
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.
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.
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
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)
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:
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
@PostConstruct
@PostActivate
protected void myPostConstructInterceptorMethod (InvocationContext ctx) {
...
ctx.proceed();
...
}
@PrePassivate
protected void myPrePassivateInterceptorMethod (InvocationContext ctx) {
...
ctx.proceed();
...
}
}
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 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().
@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
An interceptor method may have public, private, protected, or package level access but
must not be declared as final or static.
@PreDestroy
public void myPreDestroyMethod (InvocationContext ctx) {
...
ctx.proceed();
...
}
}
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:
An interceptor method may have public, private, protected, or package level access, but
must not be declared as final or static.
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
@PreDestroy
public void myPreDestroyMethod (InvocationContext ctx) {
...
ctx.proceed();
...
}
}
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();
}
...
}
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").
Using Annotations
You can specify OC4J-proprietary deployment options for an EJB 3.0 session bean using the
following OC4J-proprietary annotations:
Example 5-10 shows how to configure OC4J-proprietary deployment options for an EJB 3.0
stateless session bean using the@StatelessDeployment annotation.
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.
import javax.ejb.Stateful
import oracle.j2ee.ejb.StatefulDeployment;
@Stateful
@StatefulDeployment(
idletime=100
passivateCount=3
)
public class CartBean implements Cart {
private ArrayList items;
...
}
You can specify OC4J-proprietary deployment options using the orion-ejb-jar.xml file
element <session-deployment> as Example 5-12 shows.
The Jav
va Persiste
ence API - A Simpler Programm
ming Modell for Entity
y Persisten
nce
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 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
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.
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.
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.
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).
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.
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..
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.
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?
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.
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 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.
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
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
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;}
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
// 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
return order;
} 19
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
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
36
Entity Relationships: Example
Many to many – Inverse side
37
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
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;
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
// 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
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
54
Entity Listeners: Example – 2
55
56
Summary,
Resources,
Sun Developer Network
58
Resources
http://developers.sun.com/events/techdays/presentations/
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
4
Major Components of JPA
Portability
Features
Simplicity
6
Agenda
Entities
Entity Manager
Persistence Context
Queries
Transaction
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
10
Maintaining Relationship
> Application bears the responsibility of maintaining
relationship between objects
Before After
Employee1 Employee1
Department A Department A
Employee2 Employee2
Inconsistent!
11
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
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
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
@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
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
29
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;
...
e1.raiseByTwoDollar();
//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
tx1.begin(); tx2.begin();
e1 = findDepartment(dId);
e1 = findEmp(eId);
d1 = e1.getDepartment();
em.lock(d1, WRITE);
//version++ for d1
em.flush();
Time
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
37
Query Types – 1
NOT GOOD
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
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()
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
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;
}
8
Agenda
>Entity Manager
>Persistence Context
>Entities
>Queries
>Transaction
10
Level1 and Level2 caches
Persistence Context is a Level 1 cache
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
Detached entity
}
13
Scope of Identity
@Stateless public ShoppingCartBean implements ShoppingCart {
}
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
16
Persistence Context Propagation
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
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
21
22
Conversation with detached entity
@Stateless public ShoppingCartBean implements ShoppingCart {
@PersistenceContext EntityManager entityManager;
23
24
Conversation with Exented Persistence Context
Conversation
Persistence Context
Managed Managed Managed
Entity Entity Entity
25
@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
@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
same entity
Object Identity
only one manage entity
in PC represents a row
Data source
31
33
tx1.commit();
Time
//e1.version == 1 in db?
tx2.commit();
//Joe's rate is $14
//OptimisticLockException
34
Preventing Stale Data JPA 1.0
35
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
tx.commit();
//Joe's salary will be $14
38
JPA 2.0 Locks
39
40
JPA 2.0 Locking
Trade-offs:
lock earlier : risk bad scalability, deadlock
Lock later : risk stale data for update, get optimistic lock exception
41
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
same entity
not shared
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
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
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!
55
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
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
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")})
61
62
Navigating Relationships Detached
Entity
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
68
Mapping Inheritance Hierarchies
Employee
---------------------------
int id
String firstName
String lastName
Department dept
PartTimeEmployee FullTimeEmployee
------------------------ -----------------------
int rate double salary
69
70
Joined Subclass @Inheritance(strategy=JOINED)
Benefits EMPLOYEE
71
72
vertical partitioning CREATE TABLE Customer(
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
76
MySQL Query Analyser
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.
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:
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).
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"));
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 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.
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:
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)
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.
Figure 4.
4 Interface hierarchy of
o persisten
nt attributess in the Mettamodel AP
PI
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)).
Figure 5.
5 Metamode
el interface
e is the conttainer of ty nit
ypes in a perrsistence un
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.
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.
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.
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:
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.
Complex predicates
Certain expressions — such as in() — apply to a variable number of expressions. Listing 7
shows an example:
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:
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:
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:
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:
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:
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:
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:
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[]:
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:
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:
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
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:
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:
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:
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.
! "##
$!% !#
'(!)
!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#
"
# !$1:))
-
1:)) 4
!
#
--
))
-
"#
-&
!:
#%
!
-*
;7$
-0
<7
%
,
?C23
E>&> >"F
G<
E
.IJKL954M
-2
<7
34
-.
<34#!
"F=
+
N
H
C,*
FEH
?%
?>,
%?
F*,,"
H!
-8
))
%
,
?
E>&? ? >"F
G<
E
< IO=O
F="F=
+23P45
-9
"#
51=#
!
*!=
%
I
?%
G<
F4<
F S456
G<
FA<
F S45A
,%
S5K6
F=
-
) ! 7:!#
:
%
,
?
E>&
G<
E
H!
23"F;
5
34
&
5
>5!$
? 8
* 1
? /
* :1
#
:
8
8
D
E
/
,
&
D
# '$
!
F #
$
%1
*
!4!'
)5
<7
!
""
!
#
"
$"% &
&"
!
'(
"
"
!
!
)
! )
0
?
)
!
34
2
,:# %
? + %
!
? ? ?
%
!
8- =C= ?=
.
":!)
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 )*$6278"" 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
&&
!(
$ '-
$ '-
&*
5
5!$
!
34
&0
,))5!$
! !#
$ '$
$ '$
$ '$
$ '$ :
&2
,::7!$ 34
&.
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 /*
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:
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.
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.
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.
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.
<propertiies>
<propeerty name="eclipselink.llogging.level" value="FIN
NE"/>
</properrties>
<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
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.
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:
Vertical Partitionin
ng
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.
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 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.
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 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
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 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?
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?
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.
4. Use Named Queries when possible. Named queries can be annotated with query hints.
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.
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.
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.
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
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
Example outpout:
4384 org.jboss.Main
2172
3644 sun.tools.jps.Jps
3456 Tray
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.
Problem:
Lets say we have the following example:
import java.util.Vector;
items.add("A");
items.add("B");
items.add("C");
itemsToBeRemoved.add("B");
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.
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
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 {
buy ("SNPS",1000);
} 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);
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
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
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
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:
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.
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.
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:
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.
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.
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:
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.
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
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
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.
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.
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.
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