Preparing for EJB 3.0 You don't have to look far to see how excited people are about the new direction EJB 3.0 is taking. In fact, the entire J2EE component suite has a mandate to simplify the development process, and we can all look forward to a time when it will be much easier to develop, test and deploy our enterprise applications. EJB 3.0 is taking ease of development extremely seriously and has adjusted its model to offer the kind of POJO (Plain Old Java Object) persistence that TopLink has been doing for a decade.
This is no coincidence as the specification lead, Linda DeMichiel, chose to look outward for advice and experience from products like TopLink. This allowed the specification to follow the trails that had already been blazed by popular and proven technologies, and that had in fact become de facto practices in the industry. The EJB specification can now proudly claim that it is transitioning back to becoming both a relevant and a useful persistence specification because it is in harmony with what the vast majority of applications are already doing.
Work on the specification is progressing rapidly, and as a strong supporter of the new EJB model Oracle is actively participating in this process. Not only are we a major technical contributor but we are also currently preparing to offer a preview release of the EJB 3.0 Container technology.
Recognizing the fact that previews are not typically going to be suitable for deploying applications into production, and that the final release of EJB 3.0 will likely be sometime next year, the question arises - I like what I see, but what can I do now? The answer is that you can be proactively preparing your application for EJB 3.0. When the final draft of the specification rolls off the presses you will want your application to be in a state where it is a simple matter to migrate to the new persistence standard. Even better, you would like your application to already be using some of the features offered by the standard. In this paper I will explain how this can be done, and give advice about which features to use so that you can not only be ready for EJB 3.0, but already be most of the way there.
Get Your Architectural House in Order
The first step is to ensure that your architecture makes use of standard and accepted design patterns around persistence. This may actually require changes to your application, but is well worth the investment if you expect your application to endure the test of time. Using session facades, DAO (Data Access Object) layers or service layers are always good ideas, but in this case they are critical. Although not commonly done, if your application is already built using remote entities then you will need to rework your architecture. A remotable service layer is expected to be in place before persistence objects are accessed. If entities are being used then they should strictly be of the local variety.
Using local entities is not the end, however, since entities also provide deployers with the ability to declaratively state the transactional and security requirements for the entity. EJB 3.0 will not allow any of these attributes to be set at the entity level. Instead, the context in which entities will run will be determined by the caller, so any transactional or security context that is required should be installed or declared by its enclosing J2EE component. This separates the largely orthogonal issues of persistence from the rest of the distributed component model.
CMP Applications If you are already a CMP user then you may be thinking three things. First, you can't wait to get the new features and are ecstatic about ditching the extraneous interfaces, unnecessary bean code and tedious XML deployment descriptors that were some of the annoyances associated with previous entity bean development. The remote and local interfaces that had to extend EJBObject and EJBLocalObject, respectively, are no longer required and entities may now, if they choose to, simply implement a plain old Java interface (POJI).
Secondly, you are probably dreaming about how you will be able to more easily deploy your EJB's in the container, or even not deploy them at all but test them outside the container in a standalone environment. Because the entities are concrete plain old Java objects (POJO's), you will be able to create them the way that you always created Java objects, using new().
Lastly, you may be wondering how hard it will be to migrate some of your existing 2.1 style beans to use the new 3.0 style of programming. This is a concern that Oracle is taking to heart. In fact, we firmly believe that the strength of the transition strategy offered by a EJB product will be one of the main criteria that applications use when it comes time to choose their EJB 3.0 implementation. Our goal is to make this transition as easy as possible and we are planning and developing our implementation around this goal.
POJO Applications
The bulk of the new persistence API is accessible from the EntityManager, which may be injected into a session bean or looked up in JNDI. The EntityManager represents the transactional persistence context, which maps very closely to the TopLink UnitOfWork. Any objects managed by the UnitOfWork, or EntityManager, that are found to be dirty at the end of the transaction will be written out to the data store.
An application can insulate itself from extensive changes by abstracting the code that obtains the UnitOfWork/Session artifacts. This way the actual session that gets used can be obtained in a pluggable way. Defining the session and then allowing a surrounding layer to set it from the outside would be similar to the dependency injection paradigm that has been adopted by the EJB 3.0 Container. This pattern should be followed for all resources that are used in the application. In EJB 3.0 standard resources will be declared by the application and subsequently injected into the bean at runtime.
Adopt Standard Features
Many of the EJB 3.0 features will be recognizable in features that have been around in TopLink for a long time. By using these features you will be able to have the functionality of EJB 3.0 even though the API's are not yet completed.
Querying is one such area where you can start using EJB 3.0 features right now. TopLink provides the ability to define and execute named queries. Configuration of queries may be done statically or dynamically to allow just-in-time querying with client-based criteria.
EJB 3.0 queries will be obtained from the EntityManager, and will be executable on it. It will be possible to create a native SQL query for the rare cases when you need to go directly to SQL, and get objects back from the query. TopLink has custom queries that do exactly that, and they perform the mapping of the result set data to objects.
Query languages are often the source of migration headaches because it is very difficult to translate automatically without writing a substantive or exhaustive translation parser tool. EJB QL is a reasonable and sufficient abstraction of a relational query language and will benefit from the several new features that are being added to it. Existing EJB QL will apply and
still more EJB QL constructs and functions will enhance the query language further. Even though the query API's may not be released yet, it would make sense to write queries using EJB QL since the query language is not going to change substantially, except in an additive way. TopLink supports using EJB QL with POJOs, thus helping an application to get to a state where it is able to port its queries over to another database, another framework, or another persistence API.
Inheritance
True and natural inheritance, as Java objects were built to support and participate in, was never specified in EJB 2.1. In practice, inheritance was only possible if the vendors did not throw up obstructions, but was still quite difficult to define and manage. This will not be the case in EJB 3.0. With concrete Java objects being able to inherit from each other, and not be required to define methods that handcuffed the extent of the inheritance, you will be able to create entity inheritance hierarchies arbitrarily deep and wide.
This same flexibility is currently achievable from both within the TopLink Mapping Workbench or JDeveloper, GUI tools for mapping Java objects, as well as in the Java-based API for mapping objects. Your domain model can be produced now to adhere to the inheritance strategy that suits your application without having to wait for the specification to be released.
Optimistic Locking
The optimistic locking model that TopLink strongly supports is now going to be adopted into the EJB 3.0 model. This is a very good thing for applications, not only because it will offer huge increases in performance in the face of normal 90/10 read/write access ratios, but because it leads to the kinds of scalable architectures that modern systems require. This is a key locking paradigm that is already used by thousands of applications in the industry to achieve the scalability that web applications demand.
The flexibility of the TopLink options for locking values, and how they are determined, computed and stored, supercedes those included in the EJB 3.0 specification. The basics are clear, however, and portability is easily achieved by making use of the straightforward approach of a database column and object version field for each optimistically locked object.
This type of locking provides the added benefit of being able to use the objects in disconnected modes. Modifying data and relationship while offline can be easily supported simply by merging the data back into a transaction and verifying through the optimistic lock value that the object that was modified was not a stale copy. This aligns perfectly with what TopLink users are already doing when they merge their objects back into a unit of work.
Event Callback Listeners
The EJB model of life cycle callbacks is being adapted in two useful ways. The first is that the callbacks are more relevant to the O/R mapping runtime execution model and fine-grained events such as insertion in the database will enable actions to be taken to perform things such as auditing and other book-keeping. Secondly, non-bean event listeners can register to handle the event callbacks. This means that when you use the TopLink event listeners that you are already using the model that EJB 3.0 entities have now embraced.
Object-Relational Mappings
Perhaps the most obvious and visible support that has been provided by TopLink over the years is the ability to map object data and their relationships to relational tables. This has been a critical problem that has plagued applications that want to write object-oriented Java programs but store their data in relational databases.
The decision to add standardized metadata and semantics for object-relational mappings into EJB 3.0 is a giant step towards allowing applications the flexibility to take their application and run it on different databases and even use different persistence frameworks to do so. The first pass at the O-R mapping standard will include the most popular mappings that people now use to map their domain models, such as basic data conversion, one-to-one and many-to-many relationships, and so forth. Subsequent drafts will add more of the "deluxe" mappings that TopLink already offers, so as the specification matures it will approach even closer to TopLink as a portable solution for applications even if they have exceptional requirements.
Summary
Over the past 10 years TopLink has been incorporating the requirements of its large customer base and evolving with the way that applications persist their objects. Now that EJB 3.0 is modernizing its approach to persistence to align itself with what the majority of applications are doing, TopLink customers that have been doing POJO-based persistence for years can feel both justified and confident that standards are following their lead. Because the TopLink model is being held up as an example of how people are happy with a persistence framework, the features can be used as a step towards reaching the EJB 3.0 standard. In other words, applications that want to start now to implement EJB 3.0 can use a stable and proven product to do so, even though the specification may still be in its infancy.
TopLink is fully committed to EJB 3.0, and helping our customers move to get there. Not only will we offer migration assistance to existing TopLink customers but we are making plans to help applications that are based on other technologies as well. Stay tuned for more articles, seminars and talks about how you can benefit from adopting EJB 3.0 persistence in your applications. �
�
�
�
�
�
�
�
�
�
An Introduction to the Enterprise JavaBeans 3.0 (EJB 3) Specification The Enterprise JavaBeans (EJB) technology is a J2EE technology for the development anddeployment of component-based business applications. Applications written using theEnterprise JavaBeans architecture are scalable, transactional, and multiuser secure.
In spite of the rich features, however, the complexity of the EJB architecture has hindered itswide 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 ofthe 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:
� Make it easier for developers to develop EJBs. � 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 orminimizes callback methods required to be implemented, and reduces the complexity of theentity 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.0addresses 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 usingEJB 3.0-based enterprise beans. Limitations of EJB 2.1 Developing EJBs with EJB 2.1 hasn't been the easiest thing to do. The reasons are easy to find:
� To create a single EJB you need to create a multitude of XML deployment descriptors. � A set of three source files must be created. � Multiple callback methods must be implemented that usually are never used. � You have to throw and catch several types of unnecessary exceptions. � Yet another complaint is that the EJBs are completely untestable outside the context of
the container since components like container-managed entity beans are abstract classes.
� Finally, EJB-QL in its current form is limited in functionality and difficult to use. Theselimitations force developers to use straight JDBC and SQL, or to use other persistenceframeworks such as Toplink and Hibernate.
The sheer verbosity of the API has been one big annoyance, and EJB 3.0 makes a significantattempt to address most issues. This article covers the important aspects of this specification. The End of the Road for Deployment Descriptors The configuration of XML deployment descriptors was a major bottleneck in the path to simplifying development of EJBs. Therefore one of the primary goals of the EJB 3.0specification was to shield the developer from having to work with XML files. This isaccomplished by the use of metadata annotations that have been added to JDK 5.0 as part ofthe JSR 175 JCP specification. Annotations are a kind of attribute-oriented programming and are similar to XDoclet. However, unlike XDoclet, which requires pre-compilation, annotations are compiled into the classes by the Java compiler at compile-time. From the developer's point of view, annotations are modifiers like public/private and can be used in classes, fields, ormethods:
import javax.ejb.*; @Stateless public class MyAccountBean implements MyAccount { @Tx(TxType.REQUIRED) @MethodPermission({"customer"}) public void deposit(double money) {...} } The annotations generally are self-explanatory. The @Stateless annotation indicates that the bean is stateless. The @Tx attribute specifies the transactional demarcation for the method, and the @MethodPermission attribute specifies the users who are allowed to access themethod. So this means that there's no longer a need to write XML deployment descriptors todescribe 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 theseannotations. POJO Programming Model The critical point to note is that the above stateless session bean example is complete in itself. Disregarding the annotations, this file is a JavaBean, also known as a Plain Old Java Object(POJO). Interfaces are optional for entity beans and required for session beans and message-driven beans. However, that does not mean that you have to define an interface for yoursession bean or message-driven bean. If you do not implement an interface, a bean interfacewill be generated for you. The type of generated interface, either local or remote, is dependenton the annotation you used in the bean class. All the public methods of the bean class will beincluded as part of the automatically generated business interface: public interface ShoppingCart { public void purchase(Product product, int quantity); public void emptyCart(); } It is recommended that you generate the interface explicitly if you want to pick and choose themethods of the interface that should be exposed to the client, or want to give the interface aname different from the automatically generated name. This interface class is a Plain Old Java Interface (POJI). Both the interface and the bean classdo not have to throw unnecessary exceptions such as RemoteException.
Callback Methods
In the EJB 2.1 specification, the developer had to implement a variety of callback methods in the bean class, such as ejbActivate(),ejbPassivate(), ejbLoad(), and ejbStore(), most of which were never used. With 3.0, there is no compulsion to implement any of these methods. In EJB 3.0, bean developers do not have to implement unnecessary callback methods and instead can designate any arbitrary method as a callback method to receive notifications for life cycle events. Any callback method has to be annotated with one of the pre-defined life cycle event callback annotations. Examples of life cycle event callback method annotations include PostConstruct, PreDestroy,PostActivate, or PrePassivate. Some of the event callback methods are common to all types of enterprise beans, while some are specific to bean types such as PostPersist for entity beans.
Callback methods can be defined either in the bean class itself or in a bean listener class. A bean listener class is denoted using theCallbackListener annotation on the bean class with which it is associated. The annotations used for callback methods are the same in both cases; only the method signatures are different. A callback method defined in a listener class must take an object as a parameter, which is not needed when the callback is in the bean itself. This object parameter can be used to pass the bean instance to the method in the listener class. Here's an example of putting a callback method in an entity bean:
@Entity public class AccountBean{ @PostPersist insertAccountDetails(AccountDetails accountDetails) public void createAccount(){} }
Let's look at an example of creating a listener class and adding it to a bean class. The following code defines the callback listener AccountListener:
/* Adds callback listener to bean class */ @CallbackListener AccountListener public class AccountBean{ public void createAccount(){} }
The following code will add the callback listener AccountListener to the Account Bean:
/* Callback method defined inside a Listener class*/ public class AccountListener{ @PostPersist insertAccountDetails( AccountDetails accountDetails){} }
Since the @PostPersist is used to register a method to be called on an object that has just been inserted into the database, in this case, the method insertAccountDetails() will be invoked every time as soon as an account has been inserted using the createAccount()method in the AccountBean.
Configuration by Exception
The "Configuration by Exception" approach is the guiding methodology used in all aspects of EJB 3.0 to simplify the development effort. The intent is to simplify things for developers by forcing them to code things only where defaults are not adequate.
For instance, in many cases, defaults can be used instead of explicit metadata annotation elements. In these cases, a developer doesn't have to specify a metadata annotation to obtain the same result as if the annotation was fully specified. For example, by default, an entity bean (annotated by @Entity) has a default entity type of CMP, indicating that it has container-managed persistence. These defaults can make annotating enterprise beans very simple. The defaults always represent the most common specifications. For example, container-managed transaction demarcation (where the container, as opposed to the bean, manages the commitment or rollback of a unit of work to a database) is assumed for an enterprise bean if no annotation is specified. Similarly a default business interface is generated for session and message-driven beans which exposes all the public methods of the bean in the interface, since that is the most common use case.
Object-relational Mapping
The O/R mapping or persistence model has significantly changed from the abstract-persistence-schema-based approach, to one inspired by the various POJO-related approaches en vogue today. The O/R mapping is specified using annotations. The O/R mapping metadata expresses requirements and expectations of the application to map entities and relationship of the application domain to the database.
In EJB 2.1, developers used their own mechanisms to do certain database-specific operations like primary key generation. With EJB 3.0, support for several database-specific operations has been provided. The O/R mapping model has intrinsic support for native SQL. In this article, we do not provide details on the persistence framework, although we do provide an outline while discussing the changes in entity beans. For details check the EJB 3.0 API specification and download the EJB 3.0 persistence documentation.
Encapsulation of JNDI Lookups Using Annotations
EJB 3.0 addresses the encapsulation of environmental dependencies and JNDI access through the use of annotations, dependency injection mechanisms, and simple lookup mechanisms.
The enterprise bean's context comprises its container context and its resource and environment context. The bean may gain access to its resource references and other environment entries in its context in two ways:
1. Having the container supply it with those references such as using injections; for instance, @EJB public AddressHome addressHome; automatically looks up the EJB with the JNDI name "AddressHome."
2. Use the method Object lookup(String name) that is added to the javax.ejb.EJBContext interface. This method can be used to look up resources and other environment entries bound in the bean's JNDI environment naming context.
���
Dependency Injections A bean declares a dependency upon a resource or other entry in its environment context through a dependency annotation. A dependency annotation specifies the type of object or resource on which the bean is dependent, its characteristics, and the name through which it is to be accessed. The following are examples of dependency annotations:
@EJB(name="mySessionBean", beanInterface=MySessionIF.class) @Resource(name="myDB", type="javax.sql.DataSource.class")
Dependency annotations may be attached to the bean class or to its instance variables or methods. The amount of information that needs to be specified for a dependency annotation depends upon its usage context and how much information can be inferred from that context. Injecting arbitrary resources with @Resource The @EJB annotation only injects EJB stubs. A more generic dependency injection annotation is @Resource. Using the @Resource annotation, you can inject any service object from the JNDI using the object's JNDI name. Both global (java:/) and local (java:comp/env) JNDI trees are searched. The following examples inject a messaging connection factory and a messaging queue: @Resource (name="ConnectionFactory") QueueConnectionFactory factory; @Resource (name="queue/A") Queue queue;
For "well-known" objects such as TimerService and SessionContext, the JNDI names are standard, and therefore the @Resourceannotation can inject these objects without an explicit specification of the "name" attribute:
@Resource TimerService tms; @Resource SessionContext ctx;
Similar to the @EJB annotation, the @Resource annotation can be applied to setter methods, and the @Resources annotation can be applied to arrays. Both the @EJB and @Resource annotations are specifically tailored to the resources they inject. They simplify the developer's work.
Code sample
In the example below, the variable customerDB will be assigned a DataSource object with JNDI name myDB. The "name" attribute needs to be specified because the name of the variable we have chosen, customerDB, is different from the JNDI name myDB. The "type" attribute does not need to be specified because it can be derived from the type of the variable (for example, DataSource):
@Stateless public class MySessionBean implements MySession { //type is inferred from variable @Resource(name="myDB") public DataSource customerDB; public void myMethod1(String myString){ try { Connection conn = customerDB.getConnection(); ... catch (Exception ex) } }
Changes to the Four Types of Enterprise Beans
As we all know, there are four kinds of EJBs, and needless to say, EJB 3.0 made some changes to each type of EJB. In this section, we will look at the changes proposed for each type of EJB. One of the main advantages is that in EJB 3.0, all the managed service objects are POJOs (for example, session beans) or very lightweight components (such as message-driven beans). As you'll see, EJB 3.0 has made the development of EJBs much easier and simpler.
Stateless Session Beans
An EJB 3.0 session bean is a POJO managed by the EJB container.
The functionality of a session bean is defined by its service interface (a.k.a. business interface), which is a plain old Java interface. Using the interface class name, the session bean client retrieves a stub object of the bean from the server's JNDI. The stub object implements the bean's service interface. The client can then make calls to the bean interface methods against the stub object. The stub object simply passes the calls to the actual bean instance objects in the container, which have the implementations of those methods and do the actual work. The stub object is automatically generated by the EJB container, and it knows how to route the bean method calls to the container—you do not need to provide an implementation for the stub object. In a stateless session bean, the client-side stub object can route your method call to any bean instance that happens to be available in the container-managed object pool. Therefore, you should not have any field variables to store the bean state in the bean class.
Business interfaces Business interfaces are required for stateless session beans. It is not always necessary to define one. When undefined, they will be automatically generated for you. The type of generated interface, either local or remote, is dependent on the annotation you used in the bean class and will be a local interface if there is no annotation. All the public methods of the bean class will be included as part of the automatically generated business interface. Home interfaces Stateless session beans do not need home interfaces. The client may acquire a reference to a stateless session bean by means of injection or annotation of variables. Bean class A stateless session bean must be annotated with the stateless annotation or denoted in the deployment descriptor as a stateless session bean. The bean class need not implement the javax.ejb.SessionBean interface. The @Stateless annotation indicates that this bean is a stateless session bean: @Stateless public class TraderBean implements Trader { public void buy (String symbol, int quantity){ System.out.println("Buying "+quantity+ " of "+ symbol); } public void sell (String symbol, int quantity);{ System.out.println("Selling "+quantity+ " of "+ symbol); } } �
The session bean client Once the session bean is deployed into the EJB 3.0 container, a stub object is created, and it is registered in the server's JNDI registry. The client code obtains a stub of the bean using the class name of the interface in the JNDI. Below is an example on how to retrieve a stub instance of the TraderBean for this JSP page. You can make method calls against the stub object, and the call is transparently delegated to the bean instance in the EJB 3.0 container: private Trader tr = null; public void initialize () { try { InitialContext ctx = new InitialContext(); tr = (Trader) ctx.lookup( Trader.class.getName()); }catch (Exception e) { e.printStackTrace (); } } // ... ... public void service (Request req, Response rep) { // ... ... double res = tr.buy("SNPS",1000); } Callbacks for stateless session beans The following life cycle event callbacks are supported for stateless session beans:
� PostConstruct � PreDestroy
The PostConstruct callback occurs after any dependency injection has been performed by the container and before the first business method invocation on the bean. The PostConstruct method is invoked in an unspecified transaction context and security context.
The PreDestroy callback occurs at the time the bean instance is destroyed. The PreDestroy method executes in an unspecified transaction and security context.
Remote and local interfaces A session bean can also implement multiple interfaces, each interface targeting a different type of client. By default, the interface is for a "local" client that runs in the same JVM as the EJB 3.0 container. Method call invocations over Java references are fast and efficient. Another type of session bean interface, the remote interface, is for remote clients. When a client looks up the session bean stub via the remote interface, the container returns a serialized stub object that implements the remote interface. The remote stub knows how to pass remote procedure calls (RPCs) to the server, even in a clustered environment. The remote interface is also a plain old Java interface.
Note that using the remote interface involves the serialization and deserialization of the stub, and all calls to the bean instance are made over the network. This approach is considerably less efficient than using the local interface. You should avoid looking up a remote interface from a local client.
In the session bean implementation, you can use the @Local and @Remote annotations to specify the local and remote interfaces for this bean. Here is an example bean that implements both a local and remote interface:
@Stateless @Local ({Trader.class}) @Remote ({RemoteTrader.class}) public class TraderBean implements Trader, RemoteTrader { public void buy (String symbol, int quantity){ System.out.println("Buying "+quantity+ " of "+ symbol); } public void sell (String symbol, int quantity);{ System.out.println("Selling "+quantity+ " of "+ symbol); } } The @Local and @Remote annotations can also be used to tag session bean interfaces instead of the bean implementation class. For instance, the following code snippet specifies that the RemoteTrader is a remote interface. With that, you no longer need the @Remote tag onTraderBean.
EJB 3.0 Session Beans Stateless Session Bean Life Cycle
Implementing an EJB 3.0 Stateless Session Bean
EJB 3.0 greatly simplifies the development of stateless session beans, removing many complex development tasks. For example:
� The bean class can be a plain old Java object (POJO); it does not need to implement javax.ejb.SessionBean.
� The business interface is optional.
Home (javax.ejb.EJBHome and javax.ejb.EJBLocalHome) and component (javax.ejb.EJBObject andjavax.ejb.EJBLocalObject) business interfaces are not required.
The EJB 3.0 local or remote client of a session bean written to the EJB 3.0 API accesses a session bean through its business interface. The business interface of an EJB 3.0 session bean is an ordinary Java interface, regardless of whether or not local or remote access is provided for the bean.
� Annotations are used for many features. � A SessionContext is not required: you can simply use this to resolve a session bean to
itself � A stateless session bean does not need a remove method.
Using Annotations You can specify an EJB 3.0 session bean class method as a life cycle callback method using any of the following annotations:
� @PostConstruct � @PreDestroy � @PrePassivate (stateful session beans only) � @PostActivate (stateful session beans only)
� �
Stateful Session Beans
The stateful session bean is a session bean that maintains its internal states. If the client invokes method calls against the same bean stub, the calls are always tunneled to the same bean instance in the container. So, all field variables in the bean instance retain their values as long as the client application retains the bean stub (or reference for a local client).
Business interface The business interface of a stateful session bean on the EJB 3.0 API is also a plain Java interface. Business interfaces are required for stateful session beans. It is not always necessary to define one. When undefined they will be automatically generated for you. The type of generated interface, either local or remote, is dependent on the annotation you used in the bean class and will be a local interface if there is no annotation. All the public methods of the bean class will be included as part of the automatically generated business interface. Home interface Stateful session beans do not need home interfaces. Bean class A stateful session bean must be annotated with the stateful annotation or denoted in the deployment descriptor as a stateful session bean. The bean class does not need to implement the javax.ejb.Session Bean interface. A stateful session bean may implement theSessionSynchronization interface.
The implementation of the stateful TraderBean is straightforward. We annotated the implementation class as @Stateful and used Java objects (like Integer, String) to back up the bean properties defined in the session bean interface. The Java objects are initialized for each bean instance when it is created, at the beginning of a client session. Below is the complete code for the TraderBean class. It is important to note that the stateful session bean class must implement the serializable interface so that the container can serialize the bean instances and store them to preserve the state information when the instances are not in use.
@Stateful public class TraderBean implements Trader, Serializable { public String symbol = ""; public int quantity = 0; public void buy (String symbol, int quantity){ System.out.println("Buying "+quantity+ " of "+ symbol); } public void sell (String symbol, int quantity);{ System.out.println("Selling "+quantity+ " of "+ symbol); } public String getSymbol(){ return symbol; } public int getQuantity(){ return quantity; } // Other getter methods for the attributes ... }
The Session Bean Client Here is a sample client: Trader tr = null; if (tr == null) { try { InitialContext ctx = new InitialContext(); tr = (Trader) ctx.lookup( Trader.class.getName()); } catch (Exception e) { e.printStackTrace (); } } // Make use of the tr object Callbacks for stateful session beans Stateful session beans support callbacks for the following life cycle events: construction, destruction, activation, and passivation. The EJB 3.0 specification defines several annotations the bean can use to specify callback methods during the life cycle of the bean. The container automatically calls the annotated methods at different stages of the session bean life cycle. You can use the following annotations to tag any method in the bean class:
� @PostConstruct: The annotated method is called by the container immediately after a bean instance is instantiated. This annotation is applicable to both stateless and stateful session beans.
� @PreDestroy: The annotated method is called before the container destroys an unused or expired bean instance from its object pool. This annotation is applicable to both stateless and stateful session beans.
� @PrePassivate: If a stateful session bean instance is idle for too long, the container may passivate it and store its state to a cache. The method tagged by this annotation is called before the container passivates the bean instance. This annotation is applicable only to stateful session beans.
� @PostActivate: When the client uses the passivated stateful session bean again, a new instance is created and the bean state is restored. The method that tagged this annotation is called when the activated bean instance is ready. This annotation is only applicable to stateful session beans.
� @Init: This annotation designates initialization methods for a stateful session bean. It is different from the @PostConstructannotation in that multiple methods can be tagged with @Init in a stateful session bean. However, each bean instance can have only one @Init method invoked. The EJB 3.0 container determines which @Init method to invoke depending on how the bean is created (see the EJB 3.0 specification for details). The @PostConstruct method is called after the @Init method.
Another life cycle method annotation for a stateful session bean is the @Remove tag. It is not a callback method since the application, not the container, calls the @Remove method on the bean stub to remove the bean instance in the container object pool.
Implementing an EJB 3.0 Stateful Session Bean
EJB 3.0 greatly simplifies the development of stateful session beans, removing many complex development tasks. For example:
� The bean class can be a POJO; it does not need to implement javax.ejb.SessionBean. � The business interface is optional.
Home (javax.ejb.EJBHome and javax.ejb.EJBLocalHome) and component (javax.ejb.EJBObject andjavax.ejb.EJBLocalObject) business interfaces are not required.
The EJB 3.0 local or remote client of a session bean written to the EJB 3.0 API accesses a session bean through its business interface. The business interface of an EJB 3.0 session bean is an ordinary Java interface, regardless of whether or not local or remote access is provided for the bean.
� Annotations are used for many features. � A SessionContext is not required: you can simply use this to resolve a session bean to
itself.
Using Annotations You can specify an EJB 3.0 session bean class method as a life cycle callback method using any of the following annotations:
� @PostConstruct � @PreDestroy � @PrePassivate (stateful session beans only) � @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:
� 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.
� 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.
� Secondary storage limitations: if you cannot provide sufficient secondary storage (see "Configuring Passivation Location"), you can exchange increased memory consumption for reduced secondary storage requirements by disabling passivation
Configuring Passivation Criteria
Configuring Passivation Location
Configuring a Life Cycle Callback Interceptor Method on an EJB 3.0 Session Bean
You can specify an EJB 3.0 session bean class method as a callback interceptor method for any of the following life cycle events (see "Using Annotations"):
� Post-construct � Pre-destroy � Pre-passivate (stateful session beans only) � 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:
� @PostConstruct � @PreDestroy � @PrePassivate (stateful session beans only) � @PostActivate (stateful session beans only)
Configuring a Life Cycle Callback Interceptor Method on an Interceptor Class of an EJB 3.0 Session Bean
You can designate an interceptor method on an interceptor class of an EJB 3.0 session bean as a life cycle callback interceptor method.
To configure a life cycle callback interceptor method on an interceptor class, you must do the following:
1. Create an interceptor class. This can be any POJO class.
2. Implement the life cycle callback interceptor method. Callback methods defined on a bean's interceptor class have the following signature: Object <METHOD>(InvocationContext)
3. Associate a life cycle event with the callback interceptor method (see "Using Annotations").
A life cycle event can only be associated with one callback interceptor method, but a life cycle callback interceptor method may be used to interpose on multiple callback events. For example, @PostConstruct and @PreDestroy may appear only once in an interceptor class, but you may associate both @PostConstruct and @PreDestroy with the same callback interceptor method.
4. Associate the interceptor class with your EJB 3.0 session bean
�
Using Annotations You can specify an interceptor class method as an EJB 3.0 session bean life cycle callback method using any of the following annotations:
� @PostConstruct � @PreDestroy � @PrePassivate (stateful session beans only) � @PostActivate (stateful session beans only)
Interceptor Class
public class MyStatefulSessionBeanInterceptor { ... protected void myInterceptorMethod (InvocationContext ctx) { ... ctx.proceed(); ... } @PostConstruct @PostActivate protected void myPostConstructInterceptorMethod (InvocationContext ctx) { ... ctx.proceed(); ... } @PrePassivate protected void myPrePassivateInterceptorMethod (InvocationContext ctx) { ... ctx.proceed(); ... } }
Configuring an Around Invoke Interceptor Method on an EJB 3.0 Session Bean
You can specify one nonbusiness method as the interceptor method for a stateless or stateful session bean. Each time a client invokes a session bean business method, OC4J intercepts the invocation and invokes the interceptor method. The client invocation proceeds only if the interceptor method returns InvocationContext.proceed().
An interceptor method has the following signature:
Object <METHOD>(InvocationContext) throws Exception An interceptor method may have public, private, protected, or package level access, but must not be declared as final or static.
You can specify this method on the EJB 3.0 session bean class or on an interceptor class that you associate with an EJB 3.0 session bean
Using Annotations
Example 5-5 shows how to designate a method of a session bean class as an interceptor method using the @AroundInvoke annotation. Each time a client invokes a business method of this stateless session bean, OC4J intercepts the invocation and invokes the interceptor methodmyInterceptor. The client invocation proceeds only if the interceptor method returns InvocationContext.proceed().
Example 5-5 @AroundInvoke in an EJB 3.0 Session Bean
@Stateless public class HelloWorldBean implements HelloWorld { public void sayHello() { System.out.println("Hello!"); } @AroundInvoke protected Object myInterceptor(InvocationContext ctx) throws Exception { Principal p = ctx.getEJBContext().getCallerPrincipal; if (!userIsValid(p)) { throw new SecurityException( "Caller: '" + p.getName() + "' does not have permissions for method " + ctx.getMethod() ); } return ctx.proceed(); } } Configuring an Around Invoke Interceptor Method on an Interceptor Class of an EJB 3.0 Session Bean You can specify one nonbusiness method as the interceptor method for a stateless or stateful session bean. Each time a client invokes a session bean business method, OC4J intercepts the invocation and invokes the interceptor method. The client invocation proceeds only if the interceptor method returns InvocationContext.proceed().
You can specify this method on an interceptor class that you associate with an EJB 3.0 session bean or on the EJB 3.0 session bean class itself
To configure an interceptor method on an interceptor class, you must do the following:
1. Create an interceptor class. This can be any POJO class.
2. Implement the interceptor method. An interceptor method has the following signature: Object <METHOD>(InvocationContext) throws Exception An interceptor method may have public, private, protected, or package level access but must not be declared as final or static.
3. Designate the method as the interceptor method 4. Associate the interceptor class with your EJB 3.0 session bean For more information,
see
Using Annotations Example 5-6 shows how to specify interceptor class method myInterceptor as the interceptor method of an EJB 3.0 session bean using the@AroundInvoke annotation. After you associate this interceptor class with a session bean ("Configuring an Interceptor Class for an EJB 3.0 Session Bean"), each time you invoke a session bean business method, OC4J intercepts the invocation and invokes the myInterceptormethod. The client invocation proceeds only if this method returns InvocationContext.proceed(). Example 5-6 Interceptor Class public class MyInterceptor { ... @AroundInvoke protected Object myInterceptor(InvocationContext ctx) throws Exception { Principal p = ctx.getEJBContext().getCallerPrincipal; if (!userIsValid(p)) { throw new SecurityException( "Caller: '" + p.getName() + "' does not have permissions for method " + ctx.getMethod() ); } return ctx.proceed(); } @PreDestroy public void myPreDestroyMethod (InvocationContext ctx) { ... ctx.proceed(); ... } } Configuring an Interceptor Class for an EJB 3.0 Session Bean An interceptor class is a class, distinct from the bean class itself, whose methods are invoked in response to business method invocations and life cycle events on the bean. You can associate a bean class can with any number of interceptor classes.
You can associate an interceptor class with an EJB 3.0 stateless or stateful session bean.
To configure an EJB 3.0 session bean with an interceptor class, you must do the following:
1. Create an interceptor class .This can be any POJO class. 2. Implement interceptor methods in the interceptor class.
An interceptor method has the following signature: Object <METHOD>(InvocationContext) throws Exception
An interceptor method may have public, private, protected, or package level access, but must not be declared as final or static.
You can annotate an interceptor method as a life cycle callback or as an AroundInvoke method
3. Associate the interceptor class with your EJB 3.0 session bean. 4. Optionally configure the session bean to use singleton interceptors.
Using Annotations This section describes the following:
� Creating an Interceptor Class � Associating an Interceptor Class With a Session Bean � Specifying Singleton Interceptors in a Session Bean
Example 5-7 Interceptor Class
public class MyInterceptor { ... @AroundInvoke protected Object myInterceptor(InvocationContext ctx) throws Exception { Principal p = ctx.getEJBContext().getCallerPrincipal; if (!userIsValid(p)) { throw new SecurityException( "Caller: '" + p.getName() + "' does not have permissions for method " + ctx.getMethod() ); } return ctx.proceed(); } @PreDestroy public void myPreDestroyMethod (InvocationContext ctx) { ... ctx.proceed(); ... } }
Associating an Interceptor Class With a Session Bean You can associate an interceptor class with an EJB 3.0 session bean using the @Interceptors annotation. Example 5-8 shows how to associate the interceptor class from Example 5-7 with an EJB 3.0 session bean class.
Note that the life cycle method for @PostConstruct is a method of the EJB 3.0 session bean class itself (for more information, see"Configuring a Life Cycle Callback Interceptor Method on an EJB 3.0 Session Bean"), while the life cycle method for @PreDestroy is a life cycle callback interceptor method on the interceptor class associated with this session bean (see "Configuring a Life Cycle Callback Interceptor Method on an Interceptor Class of an EJB 3.0 Session Bean").
Example 5-8 Associating an Interceptor Class With an EJB 3.0 Session Bean
@Stateful @Interceptors(MyInterceptor.class) public class CartBean implements Cart { private ArrayList items; @PostConstruct public void initialize() { items = new ArrayList(); } ... }
Specifying Singleton Interceptors in a Session Bean
As Example 5-9 shows, you can configure OC4J to use singleton interceptor classes by setting the @StatelessDeployment or@StatefulDeployment attribute interceptorType to singleton. All instances of this session bean will share the same instance ofMyInterceptor. The MyInterceptor class must be stateless.
For more information about this attribute, see Table A-1. For more information on singleton interceptors, see "Singleton Interceptors".
Example 5-9 Specifying a Singleton Interceptor Class with an EJB 3.0 Stateful Session Bean
@Stateful @StatefulDeployment(interceptorType="singleton") @Interceptors(MyInterceptor.class) public class CartBean implements Cart { private ArrayList items; @PostConstruct public void initialize() { items = new ArrayList(); } ... }
Configuring OC4J-Proprietary Deployment Options on an EJB 3.0 Session Bean
You can configure OC4J-proprietary deployment options for an EJB 3.0 session bean using OC4J-proprietary annotations (see "Using Annotations") or using the orion-ejb-jar.xml file (see "Using Deployment XML").
Configuration in the orion-ejb-jar.xml file overrides the corresponding configuration made using OC4J-proprietary annotations.
Using Annotations
You can specify OC4J-proprietary deployment options for an EJB 3.0 session bean using the following OC4J-proprietary annotations:
� @StatelessDeployment: for stateless session beans. � @StatefulDeployment: for stateful session beans.
Example 5-10 shows how to configure OC4J-proprietary deployment options for an EJB 3.0 stateless session bean using the@StatelessDeployment annotation.
For more information on @StatelessDeployment attributes, see Table A-1.
Example 5-10 @StatelessDeployment
import javax.ejb.Stateless; import oracle.j2ee.ejb.StatelessDeployment; @Stateless @StatelessDeployment( minInstances=5, poolCacheTimeout=90 ) public class HelloWorldBean implements HelloWorld { public void sayHello(String name) { System.out.println("Hello "+name +" from first EJB3.0"); } } Example 5-11 shows how to configure OC4J-proprietary deployment options for an EJB 3.0 stateful session bean using the@StatefulDeployment annotation.
For more information on @StatefulDeployment attributes, see Table A-1.
Example 5-11 @StatefulDeployment
import javax.ejb.Stateful import oracle.j2ee.ejb.StatefulDeployment; @Stateful @StatefulDeployment( idletime=100 passivateCount=3 ) public class CartBean implements Cart { private ArrayList items; ... }
Using Deployment XML
You can specify OC4J-proprietary deployment options using the orion-ejb-jar.xml file element <session-deployment> as Example 5-12 shows.
For more information on the <session-deployment> element, see "<session-deployment>".
Example 5-12 orion-ejb-jar.xml File <session-deployment> Element
<?xml version="1.0" encoding="utf-8"?> <orion-ejb-jar xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="http://xmlns.oracle.com/oracleas/schema/orion-ejb-jar-10_0.xsd" deployment-version="10.1.3.1.0" deployment-time="10b1fb5cdd0" schema-major-version="10" schema-minor-version="0" > <enterprise-beans> <session-deployment name="MBeanServerEjb" call-timeout="0" location="MBeanServerEjb" local-location="admin_ejb_MBeanServerEjbLocal" timeout="0" ... > </session-deployment> ... </enterprise-beans> ... </orion-ejb-jar> �
The Jav The majoreferred tdevelopmSignificanplatform
EnterpristechnologDevelopmEJB 3.0 A major esimplifiestechnologobjects ("that theyafter the the Java In short, version, aPersistenboth easi
The Javaas HibercontainerSpecificaother ind
SimplicitThe JavacapabilitRequiresVirtually AddresseProvides EliminateAdds supAdds supProvides Makes it Can be uCan be u
va Persiste
or theme of vto as J2EE)
ment of enterntly, these smaintains a
se developergy. Previousment in Entetechnology,
enhancemens the entity gy. The Java"persistent y can be acceapplication PersistenceEJB 3.0 is m
and should nce API, EJBier to use an
a Persistencrnate, Oracler-managed
ation (JSR 2dividuals of n
ty at a Glanca Persistenceies that wer fewer classeliminates l
es most typiccleaner, eases the need pport for inhpport for nama Java Perseasier to tes
used outsideused with plu
ence API - A
version 5 of is ease of de
rprise Java tsimplificationall the functi
rs should nos articles, suerprise Javaan integral
nt in EJB tepersistence a Persistenceentities"), tessed at a lathat uses it API standarmuch easierresult in fas
B 3.0 technond yet richer
e API drawse TopLink, a
persistence220)has reprnote in the p
ce e API simplife not in EJBes and interlengthy deplcal specificasier, standarfor lookup c
heritance, pomed (static) sistence querst entities ou of the contauggable, thir
A Simpler
the Java Plaevelopment. technology ans have not ional richne
otice dramatiuch as IntrodBeans Technpart of the J
chnology is model and ae API deals wthe way thatater time, ant ends. In adrdizes objectr to learn anster developmlogy also offr.
s on ideas frand Java De. The Exresentation persistence c
fies the progB 2.1. Here'srfaces loyment des
ations througrdized objectcode olymorphismand dynamiry language utside of theainer rd-party per
Programm
atform, EnteChanges th
applications changed the
ess of the pre
ic simplificaduction to thnology have Java EE 5 pl
the additionadds capabiwith the wayt these objecnd the continddition to simt-relational m
nd use than ment of applfers develope
rom leading ata Objects
xpert Groupfrom expertcommunity.
gramming ms a quick list
criptors throgh annotatiot-relational m
m, and polymic queries. -- an enhan
e EJB contai
rsistence pro
ming Model
erprise Editihroughout th
much easiee platform's evious versio
ation in Entehe Java EE 5
described thlatform.
n of the new ilities that wy relational dcts are storednued existenmplifying themapping. was EJB 2.lications. Wiers an entity
persistence (JDO), andp for the ts in all of t
model for entit of its simpl
ough annotaon defaults mapping
morphic quer
nced EJB QLiner
oviders
l for Entity
on (Java EEhe platform mer, with far le
power: The on, J2EE 1.4
erprise JavaB5 Platform ahe simplifica
Java Persiswere not in E
data is mapd in a relationce of an ente entity pers
1, the technith the incluy programmi
e frameworkd well as onEnterprise these areas
ity persistenlifications an
ations
ries.
L
y Persisten
E, formerly make the ess coding. Java EE 5 4.
Beans (EJB)and Ease of ations made
tence API, wEJB 2.1
ped to Java onal databastity's state esistence mod
nology's prevusion of the Jing model th
ks and APIs n the earlier
JavaBeans as well as
nce and addsnd additions
nce
)
e in
which
se so even del,
ious Java hat is
suchr EJB 3.0 from
s s:
This articable to exin an equcode for compare Java Perare now technolog
The articcode. AltcontainerJava Platsupport fimplemenprovided
This articunderlie For more"Enterpri Content- The App- The Enti- The Clas- Persisten- Entity Id- Relation- Inheritan- Operatio- Transact- Queries
- Testing E- Summar- For More First, let'sThe App
This articApplicatitheJ2EE running The EJB availablerunning Both versstore andinformatithe custorequests get a list
Figure 1
cle supplemxamine EJBuivalent appEJB 2.1 entthem to the
sistence APIsimply callegy code is.
cle highlightshough this ar, the API catform, Standfor pluggablntation fromthat the con
cle assumesEJB 2.1. If y
e informationise Beans" in
ts plication
ities
ss Definition
nt Fields and dentity
nships
nce and Polymons on Entitietions
Entities Outsry
e Information
s look at the aplication cle uses the ion , from th1.4 Downlothe EJB 2.1
3.0 version e for downloathe EJB 3.0sions of the d display infion such as omer is substo the appliof all subsc
shows what
ents the earB 2.1 entity bplication. Motity beans the source codI. Note that id entities. Y
s some of tharticle focusan also be usdard Editione, third-part
m one vendorntainer and
s that you're you're not, sn about EJBn the Java E
Properties
morphism
es
ide of the EJB
n
application in
EJB 2.1 teche J2EE 1.4 oads page. Th version of t
of the samead here. The0 version of t
application formation aba customer'
scribed -- thication to discriptions for
t some of the
rlier articles beans in an ore specificalhat use contade for equivain the Java P
You'll see how
he importantses on the Jased outside
n (Java SE, foty persistencr can be usethe persiste
familiar witsee the chapB 3.0 and JaEE 5 Tutoria
B Container
use.
chnology versamples buhe samples the applicati
e applicatione download bthe applicatido the same
bout custom's name and
hat is, magazsplay subscra particular
e interaction
by focusingapplication lly, you'll be ainer-managlently functiPersistence w much easi
t features thava Persistenthe containe
formerly refece providersed with an Eence implem
th the basic pter "Enterprava Persistenal.
rsion of the andle. You cabundle incluion.
n is called thbundle incluion. e thing: They
mer subscriptd address, aszine, journalription-relatr customer.
ns look like.
g on entity-reand comparable to view
ged persistenioning EJB 3API, what uier and strea
at simplify tnce API ander -- for inst
erred to as Js. For exampEJB containementation bot
concepts of rise Beans" nce concepts
application, an downloadudes instruc
he Java Persudes instruc
y interact wtions to peris well as thel, or newspated informat
elated code. re them to Ew side by sidnce and rela3.0 entities w
used to be caamlined the
the EJB 3.0 its use in atance, in app2SE). The A
ple, a persister from anotth conform t
f EJB technoin the J2EEs, see the ch
the CMP Cud the samplections for in
istence Demctions for ins
with a relationiodicals. Thee type of periaper. You cantion. For exa
Here you'll EJB 3.0 entitde the sourceationships awritten to th
alled entity bEJB 3.0
version of than EJB 3.0 plications fo
API also provtence ther vendor, to JSR 220.
ology that E 1.4 Tutoriahapter
ustomer Sames bundle frostalling and
mo and is stalling and
nal database database siodical to whn submit
ample, you c
be ties e nd he beans
he
or the vides
al.
mple om
e to tores hich
an
The Ent
Let's exainterfacethe EJB
tities mine the ens are require2.1 version
Figur
ntity-related ed for the enwith that of
Figu
re 1: Java Per
code within ntities in thef the EJB 3.0
ure 2: Require
rsistence Dem
the applicate application0 version.
ed Classes an
mo Interactions
tion. First, ln. Look at Fi
nd Interfaces
s
et's look at wigure 2. Com
what classesmpare the lis
s and st in
You neeFor an ELocalAddin the apclasses -not limitein enterpthe EJBOa bean cl The Cla
Let's nowcode for tclass defnames in
An entiThe EJB fact, an Econtainerinterface ejbRemunsetEn The classmost of t
ed to code JB 3.0 entitdress -- or e
pplication's E- for local ined to entitie
prise beans oObject and Elass and a b
ass Definitiw look at thethe EJB 2.1finition. You n the Figure
ty is a Plai2.1 version
EJB 2.1 entir. Because o: ove,ejbActi
ntityContext
s must implethese method
fewer clasty, you no loeven a deployEJB 3.0 versnterfaces ands. EJB 3.0 tof any type. EJBLocalOb
business inte
ion e code for the AddressBeacan view th3.
F
in Old Javof the entity
ity bean clasof that, the b
vate, ejbPast.
ement theseds in the EJ
sses and innger need toyment descrsion, what's d a businesstechnology hIn addition, bject interfaerface, which
e entities. Lean class and
he entire enti
Figure 3: Comp
va Object (Py bean classss must impbean class m
ssivate, ejb
e callback mJB 2.1 exam
nterfaces o code interfriptor. All yorequired for
s class -- to has eliminate
you no longaces.For examh is a simple
et's start by d the EJB 3.ity bean clas
paring Class D
POJO), so ns implementsplement this must also im
bLoad, ejbSt
methods evenple in Figure
faces such aou need to pr an entity hone entity ced the requiger need to imple, a sesse Java techn
comparing .0 Address css and entity
Definitions
no boilerps the javax.interface to
mplement all
tore, setEnt
n if it doesn'te 3.
as LocalAddrovide is an
has been redlass. This siirement for aimplement sion bean nonology interf
some of the class. First, wy class by cl
late is reqejb.EntityB
o interact witof the meth
tityContext
t use them,
dressHome aentity class
duced from thimplificationa home inter
ow requires face.
key parts owe'll look at licking on th
quired Bean interfacth the EJB 2
hods in the
t, and
as is the cas
and s. So hree
n is rface
only
f the the
heir
ce. In 2.1
se for
By comparison, an EJB 3.0 entity class is a simple, nonabstract, concrete class -- a POJO, a class that you can instantiate like any other simple Java technology class, with a new operation. It does not implement javax.ejb.EntityBean or any other container-imposed interface. Because the entity class no longer implements javax.ejb.EntityBean, you are no longer required to implement any callback methods. However, you can still implement callback methods in the entity class if you need them to handle life-cycle events for the entity. Also notice the no-argument public constructor. In EJB 3.0 technology, an entity class must have a no-argument public or protected constructor. Annotations minimize what needs to be specified The @Entity metadata annotation marks the EJB 3.0 class as an entity. EJB 3.0 and the Java Persistence API rely heavily on metadata annotation, a feature that was introduced in J2SE 5.0. An annotation consists of the @ sign preceding an annotation type, sometimes followed by a parenthetical list of element-value pairs. The EJB 3.0 specification defines a variety of annotation types. Some examples are those that specify a bean's type, such as @Stateless; those that specify whether a bean is remotely or locally accessible, such as @Remote and @Local; transaction attributes, such as @TransactionAttribute; and security and method permissions, such as @MethodPermissions , @Unchecked, and @SecurityRoles. The Java Persistence API adds annotations, such as @Entity, that are specific to entities. The reliance on annotations in EJB 3.0 and the Java Persistence API demonstrates a significant design shift. Defaults make things even easier In many cases, the application can use defaults instead of explicit metadata annotation elements. In these cases, you don't have to completely specify a metadata annotation. You can obtain the same result as if you had fully specified the annotation. For example, the @Entity annotation has a name element that is used to specify the name to be used in queries that reference the entity. The name element defaults to the unqualified name of the entity class. So in the code for the Address entity, an annotation of @Entity is enough. There's no need to specify a name in the annotation. These defaults can make annotating entities very simple. In many cases, defaults are assumed when an annotation is not specified. In those cases, the defaults represent the most common specifications. For example, container-managed transaction demarcation -- in which the container, as opposed to the bean, manages the commitment or rollback of a unit of work to a database -- is assumed for an enterprise bean if no annotation is specified. These defaults illustrate the coding-by-exception approach that guides EJB 3.0 technology. The process is simpler for the developer. You need to code only when the default is inadequate.
Persiste
Let's now
PersisteIn EJB 2by definispecificaand far frpersistenpersisten
Recall thvariablesentity caprovider based acaccess thYou can,the @Tra
ent Fields w compare h
F
ence decla2.1 technologng public abtions in a de
from intuitivnce is built innt fields or p
hat an entity s, such as thn have field-accesses th
ccess, the pehe entity's pe however, ov
ansient ann
and Propehow persisten
Figure 4: Comp
rations aregy, you specbstract getteeployment de. EJB 3.0 tnto an entity
persistent pro
is a POJO. he AddressID-based or pre state of th
ersistence prersistent proverride a fielotation or th
rties nce is declar
mparing Persis
e simpler cify which fieer and setterdescriptor -- technology dy. The persisoperties.
Like a POJOD variable inroperty-basee entity dire
rovider uses operties. All ld or properthe Java keyw
red for fields
tent Field and
elds of the clr methods foan approach
does not requstent state o
O, it can havn the Addresed access. Inectly throughJavaBeans-fields and pty's default pword transie
s and proper
d Property Dec
lass need to or those fieldh that manyuire these spof an entity i
ve non abstrss class. In t
n field-basedh its instanc-style get/seproperties inpersistence ent.
rties.
clarations
be persistedds and by may programmepecificationsis represente
ract, private the Java Per
d access, thece variables. et accessor
n the entity aby marking
d in a databaking ers find clums. In essenceed either by
instance rsistence APe persistence
In propertymethods to
are persistedit with
base
msy e, its
PI, an e y-
d.
No XMLEJB 2.1 deploymepublic acdescriptolonger nePersisten Default In EJB 2correspojar.xml. specify thaccessor annotatioor propername is ausing thedescriptomultiple different The Javaapplicati
Entity I
There are
L descriptotechnology, ent descriptoccessor methor a cmp-fieeed to providnce API, to sp
mappings2.1 technolognding databBy contrasthe mappingsmethod wit
on defaults. rty, a defaulassumed. Alem as an altor might be uXML descripdatabases.
a Persistenceons.
Identity e also simpli
or needed tentity bean or, ejb-jar.xhods in the
eld element fde a deploympecify an en
s are used wgy, you definbase column, the Java Ps in the entih the @ColuIf you don't
lt mapping tlthough youternative to auseful in extptors can be
e API standa
ifications in
Figure
to declare fields are id
xml, an oftenentity bean for each persment descripntity's persist
where possne the mapps in a vendoersistence Aty class by mumn annotat specify an @o a database
u don't need annotationsternalizing oe useful in ta
ardizes objec
the way pri
e 5: Comparin
persistentdentified as pn large and cclass, you msistent field.
ptor, called atent fields.
sible ping betweenor-specific deAPI does not marking the ation. You ca@Column ae column of to specify X or to supple
object-relatioailoring obje
ct-relational
mary and co
ng Settings for
t fields persistent fiecomplex XMmust specify. In the Javaan XML desc
n an entity beployment drequire XML appropriate
an, however,annotation fof the same naML descriptement annoonal mappinect-relationa
mapping, en
omposite key
r Primary Key
elds in the bML file. In addy in the deploa Persistencecriptor in the
bean's fields descriptor, suL descriptore persistent , take advanfor a specificame as the ftors, you havotations. Using informatioal mapping in
nabling fully
ys for entitie
ys
bean's dition to codoyment e API, you ne Java
and their uch as sun-rs. Instead, yfield or prop
ntage of c persistent ffield or propve the optionng an XML on. Also, nformation t
y portable
es are specif
ding
no
ejb-you perty
field perty n of
to
fied.
No XMLIn EJB 2specifiedPersistenInstead, field or pdifferent Relation
So far, ththe persisimplificathe Custhas a onbidirectioequivalen
L descripto2.1 technolog not in the e
nce API, you you specify
persistent prways, using
nships he focus hasistence of enations that romerBean ce-to-many uonal relationnt set of rela
or needed tgy, the primaentity bean cdon't need tthe primaryoperty with g an @IdClas
s been on thentities and threlate to enticlass and comunidirectionanship with Sationships be
to specify ary key for aclass but ratto provide an
y key in the ethe @Id anss annotatio
e coding simheir fields ority relationsmpare it to tal relationshubscriptionBetween the E
the primaan entity beather in its den XML descrentity class nnotation. Yoon or an @Em
mplifications r properties. hips. To do theCustomerhip withAddrBean. Let's sEJB 3.0 enti
ry key an -- that iseployment driptor to speby marking ou can specmbeddedId
that relate Now, let's lothat, let's forBean entityressBean ansee how muities.
, its unique descriptor. Inecify an entian appropri
cify compositannotation.
to basic perook at the coocus on y. The Custo
nd a many-mch easier it
identifier -- n the Java ty's primaryiate persistete keys in tw.
sistence, thaoding
omerBean clmany is to specify
is
y key. ent wo
at is,
lass
y an
Figuree 6: ComparinClick here
ng Relationshipe for a larger i
ip Declarationimage
ns
Relationship declarations are simpler Specifying container-managed relationships in EJB 2.1 technology can be quite complex. If entity bean A has a relationship with entity bean B, you must specify abstract getter and setter methods in entity bean A for the related entity bean B. In addition, you must provide a rather lengthy entry for the relationship in the ejb-jar.xml deployment descriptor. In the Java Persistence API, you specify the relationship as you would for any POJO -- through a reference to the related entity object. In addition, you specify annotations that describe the semantics of the relationship and any database table-related metadata. You do not need an XML descriptor to specify entity relationships. Note, however, that unlike in EJB 2.1 with container-managed persistence, the application that uses the Java Persistence API is responsible for managing relationships. For example, unlike EJB 2.1 technology, the Java Persistence API requires the backpointer reference in a bidirectional relationship to be set. Assume entity A has a bidirectional relationship to entity B. In EJB 2.1 technology, all you need to do is set the relationship from A to B -- the underlying persistence implementation is responsible for setting the backpointer reference from B to A. The Java Persistence API requires the references to be set on both sides of the relationship. This means that you have to explicitly call b.setA(a) and a.setB(b). Annotations specify multiplicity and related information You declare the relationships in annotations that reference the related entities. Annotations on the persistent fields and properties specify the multiplicity of a relationship, such as one-to-many or many-to-many, and other information, such as cascade and eager fetching. (By comparison, in EJB 2.1 technology, this information is specified in vendor-specific settings.) For example, the @OneToMany annotation on the getAddresses accessor method in the Customer entity, specifies a one-to-many relationship with the Address entity. The Customer entity is the owning side of the relationship. There is no associated annotation in the inverse side of the relationship. So this is a one-to-many unidirectional relationship with the Address entity. The value specified for the cascade element in the annotation specifies that life-cycle operations on the Customer entity must be cascaded to the Address entity, the target of the relationship. In other words, when a Customer instance is made persistent, any Address instances related to the Customer are also made persistent. It also means that if a Customer instance is deleted, the related Address instances are also deleted. The FetchType value specifies eager fetching -- this tells the container to prefetch the associated entities. The owning side specifies the mapping Notice that the many-to-many relationship between the Customer and Subscription entity classes is specified using a @ManyToMany annotation in both classes and a @JoinTable annotation in the Customer class. Either Customer or Subscription could have been specified as the owning class. In this example, Customer is the owning class, and so the @JoinTable annotation is specified in the that class. The @ManyToMany annotation in the Subscription class refers to the Customer class for mapping information through a mappedBy element. Because this example uses a join table for the relationship, the @JoinTable annotation specifies the foreign key columns of the join tables that map to the primary key columns of the related entities.
Default You can even furtPersistenannotatioentity to CUSTOMdefaults.
Inherita
An imporpolymorpentities, wqueries ahierarchy
The codepolymorpPersistenthe Cust
mappingstake advantther. If you lnce Demo, yoons are needspecify the m
MER_ADDRE
ance and Prtant capabiphism, somewhere one e
against the by.
e in the EJB phism. This nce Demo doomerentity.
s are used ftage of defaulook at the cou will see aded in the Cmapping of ESS table. T
Polymorphility of the Jaething that wentity subclabase class. T
3.0 columnsample is n
oes not use tThe hierarc
Figure 7
for relationult mappingscreate.sql filea join table nustomer the Customhat's becaus
ism ava Persistewas not avaiasses anotheThe queries a
n below showot taken fromthis feature.hy is mappe
7: Support for I
nships whes to simplify e under the named CUST
er and Addrse the table
nce API is itilable in EJBer, to a relatiare treated p
ws an exampm the applic Here, Value
ed to the CU
Inheritance an
ere possibly the coding setup/sql diTOMER_ADD
ress entities name and jo
ts support foB 2.1. You caional databapolymorphic
ple of the supcation code bedCustomer
UST table:
nd Polymorph
le for relationsirectory for tDRESS. Not
to the columoin column
or inheritancan map a hiase structurcally against
pport for inhbecause the
r is an entity
hism
ship mappinthe Java tice that no
mns in the names are t
ce and ierarchy of re, and submt the entire
heritance ane Java y that extend
ng
the
mit
nd
ds
AnnotatThe @Inhthis examThis measingle tabsubclassdiscriminand rowsdiscrimindiscriminspecify thHere, Vaa value o DefaultsAs is the rely on dinheritanspecify ththe discr @Discrinecessardiscrimin EntitiesThe EJB that are nnonentity
Operati
Another performeand the Ethe EJB
tions specheritance anmple, the strans that the ble. By the wes or that mnator columns for the subnator columnnator columhe value of tluedCustom
of VCUSTOM
s can be uscase in man
defaults to funce strategy,he @InheritriminatorTyminatorCol
ry there eithenator value.
s can inher3.0 examplenot entities y can either
ions on Enpronounced
ed. For examEJB 2.1 Cus3.0 session
ify inheritnnotation idrategy specifbase class C
way, you canmaps them ton in the tabl
bclasses. Then, in this ca
mn contains the discriminmer instanceMER in the d
sed for varny other par
urther simpli, so the codeance annotaype element lumn annotaer. Also, for The default
rit from ote illustrates -- for behavbe abstract
tities d simplificatimple, look at stomerBean bean, Custo
tance dentifies a mfied by the vCustomer an also specifo separate tale to distingue @Discrimi
ase, DISC. Thstrings. Thenator columes are distindiscriminato
rious inherrts of EJB 3.ify coding. Fe sample doeation if you'rin the
ation is STRstring discriis the entity
ther entitieinheritanceior and mapor concrete
ion in the Jathe way a scompared t
omerSession
mapping straalue of the s
and its subclfy a strategyables. A singuish betweeinatorColumhe discrimine @Discriminn for the assguished fromr column.
ritance spe.0 technolog
For example,es not need re using sing
RING, so theiminator coly name.
es and frome from an enpping attribu.
ava Persistenubscription o the way th
n.
ategy for an estrategy elemlass ValuedCy that joins tgle table straen rows in thmn annotatinatorType enatorValue sociated entm other Cus
ecificationgy and the Ja, SINGLE_TAto specify itgle-table inh
e specificatiolumns, you d
m non-entntity. Howeveutes -- is als
nce API is this removed
his is done in
entity class ment is SINGCustomer athe base clasategy requirehe table for tion identifieselement spe annotation
tity. stomer insta
ns ava PersisteABLE is the. In fact, youheritance. Th
on in the coddon't need t
tities er inheritanco allowed. T
he way entityin the editCn the busine
hierarchy. InGLE_TABLEare mapped tss and its es a the base class the cifies that th
n is used to
ances by hav
ence API, you default u don't needhe default fo
de sample is to specify a
ce from POJThe base ent
y operationsCustomer.jspess interface
n E. to a
ss
he
ving
u can
d to or
not
JOs tity or
s are p file e for
Entity oIn EJB 2lookup thinterfacestate. Ththe beanrepresenmethod opertinentis synchrmethod tcomplex. By compinstance the Subsinstance the CustPOJOs.
operations2.1 technologhe bean. In d. In respons
he client can n. In the EJB
ts the Localof the Custot Subscriptironized to thtakes part co.
arison, the Jis used to fi
scription is then rem
tomer instan
Figu
s are perforgy, a client mdoing this, J
se, the EJB cthen call m
B 2.1 technolSubscriptioomerBean, tionBean inshe database ommits. Man
Java Persistind the perti
moved from thnce is remov
ure 8: Compar
rmed direcmust use theJNDI acquirecontainer cre
methods on thlogy code saonHome inthe findByPr
stance and rewhen the trny developer
tence API reqinent Custo
he Customeved from the
ring Operation
ctly on thee Java Namies an object eates an inshe JNDI-acqample aboveerface. In thrimaryKey()emoves the
ransaction inrs view this
quires no JNmer and Su
er's subscrip Subscriptio
ns on Entities
e entity ing and Dire that repres
stance of thequired object, JNDI is us
he removeSu) method finreference to
n which thisprocess as n
NDI-based loubscription
ption list. Alson's custom
ectory Interfaents the bea
e bean and it to perform ed to acquirubscriptionnds the o it. This relas CustomerBneedlessly in
ookup. An Eentities. The
so, the refermer list -- jus
face (JNDI) toan's home nitializes itsoperations
re an object n() business
ationship upBean's businndirect and
ntityManage reference t
rence to st as with
o
s on that
pdate ness
ger to
An entiAn Entitpersistenentity inson entitie DependAs illustrto get refcan use rinject a rcode samtransactithen takeDependeenvironm Transac
Transact
ty managetyManager ince context. stances and es.
dencies canrated in the ferences to rresource andresource on mple, the @Pional persistes care of obncy injection
mental refere
ctions tion-related
er managesinstance is uThe entity mfinding enti
n be injectEJB 3.0 tec
resources and environmewhich the en
PersistenceCtence contexbtaining the n can dramaences.
specification
Figure 9: C
s the entitused to manmanager is rities by the e
ed hnology cod
nd other objeent referencenterprise beContext anxt, on which reference to
atically simp
ns are also s
Comparing Tra
ties age the state
responsible fentity's prim
de example inects in an ene annotationean has a denotation injethe session
o the neededplify what yo
simplified.
ansaction-Rel
e and life cyfor creating
mary key. It a
n Figure 8, Jnterprise beans in the beaependency. Iects an Enti bean has a
d resource anou have to co
lated Specifica
ycle of entitieand removinalso allows q
JNDI is no lan's contextan class. Then the EJB 3ityManagerdependency
nd providingode to obtain
ations
es within a ng persistenqueries to be
onger requirt. Instead, yoese annotati
3.0 technologr with a y. The contag it to the ben resource a
nt e run
red ou ions gy
ainer ean. and
No XMLIn EJB 2transactiXML desthe @Traas to spespecify tr@Transasession bdemarcathe remotransactihowever, ContainIn the JacontrolleEntityTrcalled a Jthe Entitentity maand endetransacti Queries
Support enhancem
L descripto2.1 technologions in an ofcriptor is no
ansactionMaecify bean-mransaction aactionManagbean. Becaution, the annove() methodion type. So , to specify a
ner-manageava Persistend in two wayransaction AJTA entity mtyTransactianager musted outside ofion context o
s for queries hments are sh
or needed tgy, you specften lengthy ot needed to anagement
managed tranattributes. Ingement annse containernotation is nd specifies athis annota
another tran
ed entity mnce API, tranys, either thAPI. An entit
manager. An ion API is cat be a JTA enf the entity mof the sessio
has been sighown in Figu
to specify cify the trans
and complespecify tranannotation
nsactions, ann the EJB 3.notation specr-managed tnot necessara transactionation is not nnsaction type
managers ansactions invhrough JTA oty manager entity mana
alled a resountity managmanager, anon bean meth
gnificantly enure 10.
transactiosaction attribex deploymensaction attrto specify co
nd the @Tra.0 technologcifies contaitransactionsry here. The n attribute onecessary eite, such as "M
are Java Tvolving Entior by the appwhose transager whose turce-local enger. JTA entind the entityhods that in
nhanced in
on attributbutes for cont descriptoributes. Instontainer-maansactionAtgy code sampiner-manages are the defa@Transactif REQUIREDther. You woMandatory" o
TransactionityManager plication thrsactions are transactions
ntity manageity manager y manager mnvoke them.
the Java Per
tes ontainer-manor. In EJB 3.tead, you cananaged transttribute annple, the ed transactiofault type of ionAttributD, which is tould need thor "Supports
n API entitoperations
rough the controlled t
s are controler. A containtransaction
methods shar
rsistence AP
naged .0 technologn use sactions, as notation to
ons for the transaction
te annotationthe default
he annotatios".
ty managecan be
through JTAlled by ner-managedns are startedre the
PI. Some of t
gy, an
well
n on
on,
rs
A is
d d
these
No XMLIn EJB 2languageassociatecan defincreating the @Namthe creattwo namfindCustin the sea dynamPersistenJava Per
L descripto2.1 technologe (EJB QL). Ye it there witne a named -dynamic qumedQuery ateNamedQued queries atomerByFirssion bean, ic query, you
nce API provsistence que
Figu
or needed tgy, you definYou specify tth a finder o-- or static -
ueries. To creannotation. Tuery methodare defined instName andCustomerSu use the crides a Java ery language
ure 10: Compa
to specify ne a query fothe query inr select met- query in th
eate a namedThen you cr
d of the Entin the Custod findCustoSession, whireateQuery Persistence e or native S
aring Query Sp
queries or an entity bn the deploymhod for the bhe bean clasd query, youreate the pretyManager.
omer entity cmerByLastNich provides method of thquery langu
SQL in name
Specifications
bean using ment descripbean. In thess itself. Youu first defineeviously-defi. In the EJB class: Name. The nthe client c
he EntityMuage that exted or dynam
Enterprise Jptor for the be Java Persisu also have te the named ined query u 3.0 technol
named querode for the eanager. Thetends EJB Qic queries.
JavaBeans qbean, and stence API, ythe option of query using
using logy example
ies are createntity. To cre Java QL. You can
query
you f g
e,
ted eate
use
Support The JavaFor examthe namemethod snamed pdynamic query cafindCustparametequery res All querThis meareturned
The JavEJB QL hQL has laand deletquery lanfull rangeHowever enhancem
Testing
Althoughan EJB crequirempersistenPersistenentity bepropertiethrough Because entities c
Summa
The aim meets thnumber oannotateYou also deploy-ticomplex,code spe
Beyond t2.1 technentities. inheritanexercise
for dynamia Persistencemple, the Cused queries fisetParametearameters isqueries cannnot mix botomerByFirer :firstNamsults.
ries that uans that whe.
va Persistehas been a vacked some te operationnguage addse of the Javathe Java Pe
ments.
g Entities Oh this can't bcontainer is
ments for homnt fields -- mnce API remoan is a conc
es. In additioa home inteall of this m
can be more
ary of the new Jis objective of required c
e them to teluse annotame instructi, XML-basedcific attribut
these simplifnology, givinYou can tak
nce and polymore contro
ic queries ae API providestomerSessindCustomeer binds an s also a new
n use namedoth types of pstName bin
mein the nam
se the Javen a class is
ence Queryvery popularof the featus, outer join
s those featua Persistencersistence De
Outside of be demonstrnow much e
me and commade it difficuoves the requcrete entity bon, an entityrface whose
makes entitieeasily tested
Java Persistethrough a siclasses and l the containtions for objions. This an
d descriptorstes of the an
fications, thng you additike advantageymorphism tol over querie
and named qes a Query Asion class userByFirstNaargument to
w feature in td parametersparameters.
nds the firstnmed query de
va Persiste queried, all
y Languager facet of EJBres of a full
n operations,ures. It also ae query langemo does no
the Contarated in a sideasier. Previponent interult to test enuirement forbean class --y's life cycle e life-cycle mes less depend outside of
ence API is timple POJOinterfaces. Y
ner about anject-relationnnotation-bas. In many cnnotations o
e Java Persiional power e of query lato perform mes, and perf
queries is aAPI to createses the Querame and fino a named pthe Java Pers as well as p) For exampname argumefinition. Th
nce API arl subclasses
e is an enhB technologystructured q, projection,adds supporguage can beot use the Ja
ainer de-by side coously, the enrfaces, abstrntity beans or these inter- a POJO -- is controlled
methods are indent on intf the contain
to simplify th-based persYou model yn entity's chaal mappingsased approa
cases, the annly when th
istence API aand flexibilinguage enha
more powerfuform query o
added e dynamic qury API on th
ndCustomerparameter. (Brsistence APIpositional pa
ple, the setPament to the nhe getResult
re polymor that meet t
hanced quegy. However, query langu and subquert for outer je used in staava Persisten
ode comparintity bean cract entity boutside of thrfaces. The othat has per
d through thimplementedtervention byner.
he developmistence mod
your data usaracteristicss and entity ach removesnnotations' dhe defaults a
adds capabiity in developancements aul and encomoptimization
ueries and nhe entity manrByLastNamBy the way, I: both namearameters, aarameter menamed tList method
rphic the query cri
ery languagdespite its p
uage, such aseries. The Jajoin-based patic or dynance query la
ison, testingcomponent mbean classes,he containeronly thing rersistent fieldhe entity mad by the EJBy the EJB co
ment of persidel, which resing POJOs, s and the resrelationship the need fo
defaults are are inadequa
ilities that wping and usand new feampassing qus specific to
named querinager to crea
me. The Quersupport for ed queries aalthough a sethod in
d returns th
iteria are als
ge popularity, Es bulk updaava Persisteprefetching. Tmic queries
anguage
g entities outmodel -- with, and virtualr. The Java equired for ads or persistnager, not B container.ontainer, the
istent entitieeduces the and then sources it neps, as well aor often long enough. You
ate.
were not in Esing persisteatures such aueries. You c your needs
ies. ate ry
and single
he
so
EJB ate nce The .
tside h its l
an tent
. e
es. It
eeds. s and
u
EJB nt as can . In
short, uspredecesentities.
This articoffers. Yomade in a good timat the beWhat Ha
The old efor compfeatures model, anmodel. Ewant to ssome of t
Conclusi
EJB 3.0 simplifyinobjects (Pcovered iFor detaidocumen
BEA SystDetails ofinalized.
sing the Javasors, yet it o
cle only highou'll find moEJB 3.0 tecme to try ou
eginning of thappens to th
entity modelpatibility reasin EJB 3.0, nd thinking
EJB 3.0 planstick to the othe new func
ion
goes a long ng developmPOJOs) rathin detail in tils, check thntation.
tems is workon the implem.
a Persistencoffers a more
hlights the sore extensivehnology, by
ut EJB 3.0 tehis article fohe Old Entit
is still goingsons. The Exwhich woulabout maki
ns to extend old programctionality.
way toward ment, facilitaher than on cthis article ishe EJB 3.0 A
king activelymentation a
e API is muce robust API
simplificatione informationexamining t
echnology anor some goodty Model?
g to remain xpert Groupd potentiallying those avathe EJB-QLming model
making theating test-dricomplex APIs the new pe
API specificat
y on its EJB3and the timel
ch simpler aI for creating
ns and enhan about the the Enterprind the Java d places to s
a part of EJp is currentlyy be useful failable for p
L for the EJBfor a while,
EJB prograiven developIs. One of thersistence fration, and do
3 implementline will be p
and more intg, managing
ancements thAPI, as well ise JavaBeanPersistence
start.
JB, and it alwy looking at for people us
people using B 2.1-style C you will be
amming expepment, and fhe importantamework de
ownload the
tation strateprovided on
tuitive than g, and using
hat the Java as other simns 3.0 Speci
e API. See th
ways will bea number osing the old the older pr
CMP entity bable to do t
erience a plefocusing mort aspects thaefined in theEJB 3.0 per
egy in BEA Wthis Web sit
it's persistent
a Persistencemplificationsification. Noe Try It Out
e a part of EJof the new
programminrogramming eans. So if yhat and still
easant one bre on plain Jat we have n specificatiorsistence
WebLogic Sete when they
e API s ow is ! box
JB,
ng
you l use
by Java
not on.
erver. y are
This figumanaged
To transiJava obje
To transimethod pPrePersisPostPersi
To transiserialized
To transithe Entit
While in on the enthe entitythe entity
Also whilfollowingthe databinvoked.
re shows thd, detached
ition from thect construc
ition from thpersist is invst (if any) is ist (if any) is
ition from thd to another
ition from detyManager m
the managentity or use ty method any method an
le in the mag occurs: Entbase fetch co
e life cycle od, and remov
he does not ction occurs
he new statevoked with tinvoked, the
s invoked.
he managedtier.
etached bacmethod merg
ed state, witthe entity punnotated as nnotated as
anaged statetityManagerompletes, an
Entit
of an EJB 3.0ved.
exist state such as Obj
e to the manhe new objee database in
state to the
ck to managge is invoked
hin a transaublic API: whPreUpdate PostUpdate
e, within a trr method refrnd the entity
ty Life Cyc
0 entity. The
to the new sject obj = ne
naged state, ect as argumnsert compl
e detached s
ged, the follod with the en
actional conhen the tran(if any) is inve (if any) is in
ransactionafresh is invoky method an
cle
ere are five s
state, the folew Object().
the followinment, the ent
etes, the ent
state, the fol
owing occursntity object a
ntext, you cnsaction comvoked, the dnvoked.
al context, tked with the
nnotated as P
states: does
llowing occu
ng occurs: Entity method tity method
llowing occu
s: the entity as argument
can execute mmits, the fodatabase upd
to refresh the entity objePostLoad (if
�
not exist, n
urs: plain old
ntityManageannotated aannotated a
urs: the entit
is de-serialit.
an update qollowing occudate comple
he entity, thect as argumf any) is then
new,
d
er as as
ty is
ized,
query urs:
etes,
e ment,
n
�
�
�
�
�
�
�
�
A persist
� Eit
� D� V� P
nP
Am
� Mclp
Configu Using AnYou can following
� @� @� @� @� @� @� @
tence unit i
Entity managt, and entity Data source (Vendor extenersistent maamely, entitersistent Ma
All persistentmapping to a
Mapping metlasses to datersistent ma
uring a Life
nnotations specify an E
g annotation@PrePersist @PostPersist @PreRemove @PostRemove@PreUpdate @PostUpdate@PostLoad
is a logical g
ger: includinmanager co
(see "Specifynsions (see "Canaged classty classes, emanaged Clas
t managed ca single data
tadata: the intabase tableanaged class
e Cycle Cal
EJB 3.0 entits:
e
grouping of t
ng, entity maonfiguration.ying a Data SConfiguring ses: the clasmbeddable cses Does Th
lasses in a gbase.
nformation tes. You can sses and orm
llback Met
ty class met
the following
anager provi. Source in a Vendor Exte
sses you inteclasses, andhis Persisten
given persist
that describspecify mapp
m.xml files (se
thod on an
thod as a life
�
g:
ider, the ent
Persistence ensions in aend to manad mapped sunce Unit Inclu
tence unit m
es how to mping metadaee "What is
n EJB 3.0 E
e cycle callba
tity manager
Unit"). a Persistenceage using anuperclasses (ude?").
must be collo
map persistenata using anthe orm.xml
Entity
ack method
rs obtained f
e Unit"). n entity mana(see "What
ocated in the
nt managed nnotations onl File?").
using any o
from
ager,
eir
n
of the
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:
� @PrePersist � @PostPersist � @PreRemove � @PostRemove � @PreUpdate � @PostUpdate � @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 } �
1
Simplifying Persistence using JPA
Sridhar Reddy
Technology Evangelist
Sun Microsystems, Inc.
2
Goal of the Talk
Learn about the enhancements made in Java to simplify Persistence
The Java Persistence API was developed by the EJB 3.0 (JSR 220)
We will take an in-depth look at the Java Persistence API (JPA)
3
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
4
Java Persistence Requirements• Simplification of the persistence model
> Elimination of deployment descriptor
• Light-weight persistence model
> In terms of programming and deployment model as well as runtime performance
• Testability outside of the containers
> Create test clients that would use entities in a non-managed environment
• Domain modelling through inheritance and polymorphism
• Object/Relational (O/R) mapping
• Extensive querying capabilities
5
Common Java Persistence BetweenJ2SE and J2EE Environments
• Persistence API expanded to include use outside of EJB container
• Evolved into “common” Java persistence API> You can use new Java persistence API in Java SE,
Web, and EJB applications
• Support for pluggable, third-party persistence providers> Through persistence.xml
6
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
7
Entity Example@Entity
public class Customer implements Serializable {
@Id protected Long id;
protected String name;
@Embedded protected Address address;
protected PreferredStatus status;
@Transient protected int orderCount;
public Customer() {}
public Long getId() {return id;}
protected void setId(Long id) {this.id = id;}
public String getName() {return name;}
public void setName(String name) {this.name = name;}
…
}
8
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
9
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
10
Java Persistence Programming Model
• Entity is a POJO (no need to implement EntityBean)
• Use of Annotation to denote a POJO as an entity (instead of deployment descriptor)
// @Entity is an annotation
// It annotates Employee POJO class to be Entity
@Entity
public class Employee {
// Persistent/transient fields
// Property accessor methods
// Persistence logic methods
}
11
Persistence Entity Example
@Entity
public class Customer {
private Long id;
private String name;
private Address address;
private Collection<Order> orders = new HashSet();
public Customer() {}
@Id public Long getID() {
return id;
}
protected void setID (Long id) {
this.id = id;
}
Annotated as “Entity”
Getters/setters to access state
@Id denotes primary key
12
Persistence Entity Example (Contd.)...
// Relationship between Customer and Orders
@OneToMany
public Collection<Order> getOrders() {
return orders;
}
public void setOrders(Collection<Order> orders) {
this.orders = orders;
}
// Other business methods
...
}
13
Client View: From Stateless Session Bean@Stateless
public class OrderEntry {
// Dependency injection of Entity Manager for
// the given persistence unit
@PersistenceContext
EntityManager em;
public void enterOrder(int custID, Order newOrder){
// Use find method to locate customer entity
Customer c = em.find(Customer.class, custID);
// Add a new order to the Orders
c.getOrders().add(newOrder);
newOrder.setCustomer(c);
}
// other business methods
}
14
Client Code: From Java SE Client
public static void main(String[] args) {
EntityManagerFactory emf =
Persistence.createEntityManagerFactory("EmployeeService");
EntityManager em = emf.createEntityManager();
Collection emps = em.createQuery("SELECT e FROM Employee e")
.getResultList();
// More code
15
Demo:Demo:
Creating Entities from ExistingCreating Entities from ExistingDatabase TablesDatabase Tables
www.netbeans.org/kb/docs/java/compile-on-save-screencast.htmlwww.netbeans.org/kb/docs/java/compile-on-save-screencast.html
16
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
17
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
18
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
19
Persist Operation
public Order createNewOrder(Customer customer) {
Order order = new Order(customer);
// Transitions new instances to managed. On the
// next flush or commit, the newly persisted
// instances will be inserted into the datastore.
entityManager.persist(order);
return order;
}
20
Find and Remove Operations
public void removeOrder(Long orderId) {
Order order =
entityManager.find(Order.class, orderId);
// The instances will be deleted from the datastore
// on the next flush or commit. Accessing a
// removed entity has undefined results.
entityManager.remove(order);
}
21
Merge Operation
public OrderLine updateOrderLine(OrderLine orderLine) {
// The merge method returns a managed copy of
// the given detached entity. Changes made to the
// persistent state of the detached entity are
// applied to this managed instance.
return entityManager.merge(orderLine);
}
22
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
23
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 managers
24
@TransactionAttribute Annotation
• TransactionAttributeType.REQUIRED
• TransactionAttributeType.REQUIRES_NEW
• TransactionAttributeType.MANDATORY
• TransactionAttributeType.NOT_SUPPORTED
• TransactionAttributeType.NEVER
• TransactionAttributeType.SUPPORTS
25
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 ..)
26
Transaction & Persistence Context Example @Stateless
public class AuditServiceBean implements AuditService {
@PersistenceContext(unitName="EmployeeService")
private EntityManager em;
@TransactionAttribute(TransactionAttributeType.REQUIRED) //Default
public void logTransaction(int empId, String action) {
// verify employee number is valid
if (em.find(Employee.class, empId) == null) {
throw new IllegalArgumentException("Unknown employee id"); }
LogRecord lr = new LogRecord(empId, action);
em.persist(lr);
}
@TransactionAttribute(TransactionAttributeType.REQUIRES_NEW)
public void logTransaction2(int empId, String action) {
logTransaction(empId, action);
}
27
Transactions & Persistence Context Example@Stateless
public class EmployeeServiceBean implements EmployeeService {
@PersistenceContext(unitName="EmployeeService")
private EntityManager em;
@EJB
AuditService audit;
public void createEmployee(Employee emp) {
em.persist(emp);
audit.logTransaction(emp.getId(), "created employee");
}
public void createEmployee2(Employee emp) {
em.persist(emp);
audit.logTransaction2(emp.getId(), "created employee");
}
28
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
29
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
30
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
31
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
32
Simple Mappings
CUSTOMER
ID NAME C_RATING PHOTO
@Entity(access=FIELD)
@Id
@Lob
public class Customer {
int id;
String name; int c_rating;
Image photo;}
33
public class Customer {
int id;
String name;
int c_rating;
Image photo;}
Simple Mappings
@Entity(access=FIELD)
@Column(name=“CREDIT”)
@Id
@Lob
CUSTOMER
ID NAME CREDIT PHOTO
34
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
35
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
36
Entity Relationships: ExampleMany to many – Owning side
37
Entity Relationships: ExampleMany to many – Inverse side
38
Entity Relationships and Cascading Behavior
• Cascading is used to propagate the effect of an operation to associated entities
• Cascading operations will work only when entities are associated to the persistence context> If a cascaded operation takes place on detached
entity, IllegalArgumentException is thrown
• Cascade=PERSIST
• Cascade=REMOVE> Not advisable to use it on relationships other than one-
to-one and one-to-many relationships
• Cascade=MERGE Cascade=REFRESH
• Cascade=ALL
39
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
40
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(..)
41
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)
42
Single Table Strategy
• All the classes in a hierarchy are mapped to a single table
• Annotation to the parent Entity> @Inheritance(strategy=InheritanceType.SINGLE_TABLE)
• Root table has a discriminator column whose value identifies the specific subclass to which the instance represented by row belongs> @DiscriminatorColumn(columnDefinition="MYDTYPE")
43
Single Table Strategy Example // Parent Entity
@Entity
@Inheritance(strategy=InheritanceType.SINGLE_TABLE)
//default is SNGE_TABLE
public class Person implements Serializable {...}
private String name;
@Entity // Child Entity
public class Student extends Person {...}
private String school;
private double grade;
@Entity // Child Entity
public class Teacher extends Person {...}
44
Single Table Strategy Example
45
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)
46
Joined Table Strategy Example // Parent Entity
@Entity
@Inheritance(strategy=InheritanceType.JOINED)
@DiscriminatorColumn(columnDefinition="MYDTYPE")
public class Person implements Serializable {...}
private String name;
// Child Entity
@Entity
public class Student extends Person {...}
private String school;
private double grade;
// Child Entity
@Entity
public class Teacher extends Person {...}
47
Demo:Demo:
Using different strategies forUsing different strategies forInheritance ans how database Inheritance ans how database
tables are created:tables are created:SINGLE_TABLESINGLE_TABLE
JOINEDJOINED
48
Entity Inheritance Strategy • SINGLE_TABLE [default]
> All the classes in a hierarchy are mapped to a single table
> This strategy provides good support polymorphic relationships between entities and queries that cover the entire class hierarchy
> May contain null fields for some subclass data
• TABLE_PER_CLASS > Each class in a hierarchy mapped to a separate table and
hence, provides poor support for polymorphic relationships
> requires SQ union or separate SQL queries for each subclass
• JOINED> no null fields => compact data
> This provides good support for polymorphic relationships, but requires one or more join operations – may result in poor performance
Embedded Objects Embedded Objects
50
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
51
Embedded Objects
public class Customer {
int id;
CustomerInfo info;}
CUSTOMERID NAME
CREDIT PHOTO
public class CustomerInfo {
String name;
int credit;
Image photo;
}
@Entity
@Embedded
@Id
@Embeddable
@Lob
52
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
53
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
54
Entity Listeners: Example – 1
55
Entity Listeners: Example – 2
56
Entity Listeners: Example – 3
Summary,Summary,Resources,Resources,Sun Developer NetworkSun Developer Network
58
• Simplifies persistence model
• Supports Light-weight persistence model
• Support both J2SE and J2EE environments
• O/R mapping through annotation
• Extensive querying capabilities
Java Persistence Summary
59
Resourceshttp://developers.sun.com/events/techdays/presentations/
• Glassfish persistence homepage> https://glassfish.dev.java.net/javaee5/persistence
• Persistence support page> https://glassfish.dev.java.net/javaee5/persistence/entit
y-persistence-support.html
• Blog on using persistence in Web applications> http://weblogs.java.net/blog/ss141213/archive/2005/12
/using_java_pers.html
• Blog on schema generation> http://blogs.sun.com/roller/page/java2dbInGlassFish#a
utomatic_table_generation_feature_in
60
Sridhar Reddy Technology Evangelist
Sun Microsystems, Inc
1
Java Persistene API:Java Persistene API:Best PracticesBest Practices
Srinidhi Nirgunda
Architecture Solution Team
2
Agenda
Entities
Entity Manager
Persistence Context
Queries
Transaction
3
Objective
>Highlight and discuss about the best practices for JPA
> Assumption – You already know JPA
> Not an introductory JPA session• Discuss advance concepts
4
Very Brief Overview of JPA
>Introduced as part of JavaEE 5• Simplified Persistence model
>POJO based programming model•No interfaces, convention, annotation based
> Support rich domain modeling•Inheritance and polymorphism
> Expanded query language
> Standardize object/relational mapping
> Usable in JavaEE and JavaSE•Unified persistence model across the Java platform
5
Major Components of JPA
6
Why to follow Best Practices?
Features
Portability
Simplicity
7
Agenda
EntitiesEntities
Entity Manager
Persistence Context
Queries
Transaction
8
Things to Remember About Entities
> Are not EntityBeans!!!
> Entities are POJOs•No remote calls involved, methods are executed locally
•Methods can now be coarse or fine grained
> Entity states are New, Managed, Detached, Removed•No remote or local concept
> Need to be aware when entities are detached•Outside of transaction context
•Remember to merge
9
Primary Keys
> Annotated by @Id
> For simple @Id, can specify primary key generator•TABLE – most portable
•SEQUENCE, IDENTITY �Uses the database's sequence and identity column
�Not portable across database or persistence manager
•AUTO – pick the best strategy
> For portability, specify generator to give mapping details
@TableGenerator(name=”mygen”, table=”ID_TABLE”, pkColumnName=”GEN_KEY”, pkColumnValue=”EMP_ID”, valueColumnName=”GEN_VALUE”)
@Id @GenerateValue(strategy=TABLE, generator=”mygen”)long id;
ID_TABLEGEN_KEY GEN_VALUE
EMP_ID Last generated value
10
Example – Domain Model
@Entity public class Employee {@Id private int id;private String firstName;private String lastName;@ManyToOne(fetch=LAZY)private Department dept;
...}@Entity public class Department {
@Id private int id;private String name;@OneToMany(mappedBy = "dept", fetch=LAZY)private Collection<Employee> emps = new ...; ...
}
11
Maintaining Relationship
> Application bears the responsibility of maintaining relationship between objects
Department A
Employee1
Employee2
Employee3
Employee1
Employee2
Employee3
Before After
Inconsistent!
Department B
Department A
Department B
12
Example – Managing Relationship
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();
}
INCORRECT
13
Example – Managing Relationship
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();
}
CORRECT
14
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
15
Choosing Between EAGER And LAZY
> EAGER – too many joins?
> LAZY – N + 1 problem
> Use a different query•Return only employees that matches WHERE clause
•Benefits of EAGER and LAZY
SELECT d.id, ..., e.id, ... FROM Department d left join fetch Employee e
on e.deptid = d.id
SELECT d.id, ... FROM Department d // 1 timeSELECT e.id, ... FROM Employee e
WHERE e.deptId = ? // N times
SELECT d from Department dLEFT JOIN FETCH d.employees
WHERE d.id = 1
16
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 loadedd.getEmployees().size();
17
Using Cascade@Entity public class Employee {
@Id private int id;private String firstName;private String lastName;@ManyToOne(cascade=MERGE, fetch=LAZY)private Department dept;
...}@Entity public class Department {
@Id private int id;private String name;@OneToMany(mappedBy = "dept"
cascade=MERGE, fetch=LAZY)private Collection<Employee> emps = new ...;@OneToManyprivate Collection<DepartmentCode> codes; ...
}
Employee
Department
DepartmentCode
cascade=ALL
X
18
Mapping Inheritance Hierarchies
Employee
---------------------------
int id
String firstName
String lastName Department dept
PartTimeEmployee
------------------------
int rate
FullTimeEmployee
-----------------------
double salary
19
Single Table Per Class
> Benefits•Simple
•No joins required
> Drawbacks•Not normalized
•Requires columns corresponding to subclasses' state to be null
•Table can have too many columns
@Inheritance(strategy=SINGLE_TABLE)
EMPLOYEE
---------------------------
ID Int PK,
FIRSTNAME varchar(255),
LASTNAME varchar(255),
DEPT_ID int FK,
RATE int NULL,
SALARY double NULL,
DISCRIM varchar(30)
20
Joined Subclass
> Benefits•Normalized database
•Database view same as domain model
•Easy to evolve domain model
> Drawbacks•Poor performance in deep hierarchies
•Poor performance for polymorphic queries and relationships
@Inheritance(strategy=JOINED)
ID int PK,
FIRSTNAME varchar(255),
LASTNAME varchar(255),
DEPT_ID int FK,
DISCRIM varchar(30)
ID int PK FK,
RATE int NULL
ID int PK FK,
SALARY double NULL
EMPLOYEE
PARTTIMEEMPLOYEE
FULLTIMEEMPLOYEE
21
Table Per Class
> Benefits•No need for joins if only leaf classes are entities
> Drawbacks•Not normalized
•Poor performance when querying non-leaf entities-union
•Poor support for polymorphic relationships
> This strategy is not mandatory
@Inheritance(strategy=TABLE_PER_CLASS)
ID int PK,
FIRSTNAME varchar(255),
LASTNAME varchar(255),
DEPT_ID int FK
ID int PK,
FIRSTNAME varchar(255),
LASTNAME varchar(255),
DEPT_ID int FK,
SALARY double NULL
ID int PK,
FIRSTNAME varchar(255),
LASTNAME varchar(255),
DEPT_ID int FK,
RATE int NULL
EMPLOYEE
PARTTIMEEMPLOYEE
FULLTIMEEMPLOYEE
22
Agenda
Entities
Entity ManagerEntity Manager
Persistence Context
Queries
Transaction
23
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
24
Threading Models and Injections
> Field injection is only supported for instance variable• Not thread-safe
> Threading models for JPA components• EntityManager is not thread-safe
• EntityManagerFactory is thread-safe
> Dangerous to inject non threadsafe objects into stateless components• Inconsistent data
• Data viewable to other threads
> Off topic – same goes for other JavaEE 5 components• Eg. EJBs, web services, other resources
25
Beware of Injected EntityManagers
public class ShoppingCartServlet extends HttpServlet {@PersistenceContext EntityManager em;protected void doPost(HttpServlet req, ...) {
Order order order = ...;em.persist(order);
}
public class ShoppingCartServlet extends HttpServlet {@PersistenceUnit EntityManagerFactory factory;protected void doPost(HttpServlet req, ...) {
EntityManager em = factory.createEntityManager();Order order order = ...;em.persist(order);
}
WRONG
CORRECT
26
Agenda
Entities
Entity Manager
Persistence ContextPersistence Context
Queries
Transaction
27
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
28
Persistence Context and Caching
String empId = “12345”;Employee employee = em.find(Employee.class, empId);//Do something with it. . .
//Reload the employeeemployee = em.find(Employee.class, empId);
Query query = em.createQuery(“SELECT e FROM Employee e “+ “WHERE e.ID = :ID”).setParameter(“ID”, empId);
employee = (Employee)query.getSingleResult();
Meanwhile empId 12345 have been changed
Will I get the new data for employee?
29
Persistence Context as Cache
> Answer: It depends
> Entities managed by persistence context• Are not refresh until EntityManager.refresh() is
explicitly invoked
• Are not synchronized with database until EntityManager.flush() is invoked either explicitly or implicitly when persistence context is closed
> Entities remained managed by persistence context until• EntityManager.clear() is invoked
• Transaction commits
30
Concurrency - Optimistic vs Pessimistic
> Optimistic lock is the default• Based on version consistency
• Suitable for application with few parallel updates
> Pessimistic lock for lots of parallel updates• May result in lots of rollback – be prepare to handle them
• Not supported in JPA
• Need to resort to vendor specific extensions
• Eg. Glassfish/EclipseLink – eclipselink.pessimistic-lock property
31
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
> Perform read or write locks on entities
public class Employee {@ID int id;@Version Timestamp timestamp;...
32
Preventing Parallel Updates – 1
tx1.begin();//Joe's employee id is 5//e1.version == 1e1 = findPartTimeEmp(5);
e1.raiseByTwoDollar();
tx1.commit();//e1.version == 2 in db
tx2.begin();//Joe's employee id is 5//e1.version == 1e1 = findPartTimeEmp(5);
//Joe's current rate is $9if(e1.getRate() < 10)
e1.raiseByFiveDollar();
//e1.version == 1 in db?tx2.commit();//Joe's rate will be $14//OptimisticLockException
Tim
e
33
Preventing Stale Data
tx1.begin();d1 = findDepartment(dId);
//d1's original name is//”Engrg”d1.setName(“MarketEngrg”);
tx1.commit();
tx2.begin();
e1 = findEmp(eId);d1 = e1.getDepartment();em.lock(d1, READ);if(d1's name is “Engrg”)
e1.raiseByTenPercent();
//Check d1.version in dbtx2.commit();//e1 gets the raise he does//not deserve//Transaction rolls back
Tim
e
34
Preventing Parallel Updates – 2
tx1.begin();e1 = findDepartment(dId);
//d1's original name is//”Engrg”d1.setName(“MarketEngrg”);
tx1.commit(); //tx rolls back
tx2.begin();
e1 = findEmp(eId);d1 = e1.getDepartment();em.lock(d1, WRITE);
//version++ for d1em.flush();
if(d1's name is “Engrg”) e1.raiseByTenPercent();
tx2.commit();
Tim
e
35
Bulk Updates
> Update directly against the database• By pass EntityManager• @Version will not be updated
> Entities in persistence context may be outdatedtx.begin();int id = 5; //Joe's employee id is 5e1 = findPartTimeEmp(id); //Joe's current rate is $9 //Double every employee's salaryem.createQuery(
“Update Employee set rate = rate * 2”).executeUpdate();
//Joe's rate is still $9 in this persistence contextif(e1.getRate() < 10)
e1.raiseByFiveDollar(); tx.commit();//Joe's salary will be $14
36
Agenda
Entities
Entity Manager
Persistence Context
QueriesQueries
Transaction
37
Query Types – 1
> Named query• Like findByXXXX() from EntityBeans• Compiled by persistence engine
• Created either with @NamedQuery or externalized in orm.xml
> Dynamic query• Created dynamically by passing a query string to
EntityManager
• Beware of SQL injection, better to use with named parameters
38
Query Types – 1
Query query = em.createQuery(“select ...”);
q = em.createQuery(“select e from Employee e WHERE ”+ “e.empId LIKE '” + id + “'”);
q = em.createQuery(“select e from Employee e WHERE ”+ “e.empId LIKE ':id'”);
q.setParameter(“id”, id);
NOT GOOD
GOOD
39
Query Types – 2
> Native query• Leverage the native database querying facilities
• Not portable – ties queries to database
40
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);//Do something to orderem.persist(order);Query q = em.createNamedQuery(“findAllOrders”);q.setParameter(“id”, orderNumber);q.setFlushMode(FlushModeType.COMMIT);//Newly added order will NOT visible – not committedList list = q.getResultList();
41
Agenda
Entities
Entity Manager
Persistence Context
Queries
TransactionTransaction
42
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
43
JTA and RESOURCE_LOCAL EntityManager
> 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()
44
Creating JTA Transactions
> Create EntityManger inside a JTA transaction• Get an instance of JTA transaction from container or client
container (for JavaSE)
> Join a JTA transaction
@Resource UserTransaction utx;. . .utx.begin();EntityManager em = emf.createEntityManager();//em is now JTA
@Resource UserTransaction utx;. . .EntityManager em = emf.createEntityManager();//em is is RESOURCE_LOCALutx.begin();em.joinTransaction();
45
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
46
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
47
Srinidhi Nirgunda
1
Java Persistence API:Best PracticesCarol McDonaldJava Architect
2
Agenda
>Entity Manager>Persistence Context>Entities>Schema & Queries>Transaction
3
PersistenceContext
EntityManagerpersist()remove()refresh()merge()find()createQuery()createNamedQuery()contains()flush()
EntityManagerAPI for managing entities set of entities managed by
Entity Manager
4
Catalog Java EE Application
DB
Registration Application
Managed Bean
JSF ComponentsSessionBean
EntityClass
Catalog
Item
ManagedBean
5
EJB EntityManager Example@Statelesspublic 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;
}}
6
Catalog Spring JPA Application
DB
Registration Application
Managed Bean
JSF ComponentsSpringBean
EntityClass
Catalog
Item
ItemController
SpringFramework
7
Spring with JPA@Repository@Transactionalpublic 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;
}
Component StereotypeSpring transactions use aop
8
Container vs Application ManagedContainer managed entity managers (EJB, Spring Bean,
Seam component)• Injected into application• Automatically closed• JTA transaction – propagatedApplication 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
9
Agenda
>Entity Manager>Persistence Context>Entities>Queries>Transaction
10
PersistenceContext
EntityManagerpersist()remove()refresh()merge()find()createQuery()createNamedQuery()contains()flush()
Persistence Context set of entities managEntity Manager• Persistence context acts
as a first level cache for entities
• Two types of persistence context> Transaction scoped> Extended scoped
persistence context
11
Level1 and Level2 caches
The terms “Java Virtual Machine” and “JVM” mean a Virtual Machine for the Java™ Platform. Source:http://weblogs.java.net/blog/guruwons/ar
Persistence Context is a Level 1 cache
Transaction Transaction Transaction
Persistence Context(EntityManager)
Persistence Context(EntityManager)
Persistence Context(EntityManager)
L2 Cache(Shared Cache)
Entity managers for a specific PersistenceUnit on a given Java Virtual Machine (JVM™)
12
Persistence ContextManaged
EntityManaged
Entity
NewEntity
RemovedEntity
DetachedEntity
Transaction commit
new()
persist()
Updates
remove()
Merge()find()
PC ends
Entity Lifecycle
Guaranteed Scope ofObject Identityonly one manage entityin PC represents a row
ManagedEntity
13
Entity Lifecycle Illustrated – The Code
@Stateless public ShoppingCartBeanimplements ShoppingCart {
@PersistenceContext EntityManager entityManager;
public OrderLine createOrderLine(Product product, Order order) {
OrderLine orderLine = new OrderLine(order, produentityManager.persist(orderLine);return (orderLine);
}
}
New entity
Managed entity
Detached entity
Persisten
14
Scope of Identity
@Stateless public ShoppingCartBean implements ShoppingCart {
@PersistenceContext EntityManager entityManager;
public OrderLine createOrderLine(Product product,Order order) OrderLine orderLine = new OrderLine(order, productentityManager.persist(orderLine);
OrderLine orderLine2 =entityManager.find(OrderLine,orderLine.getId()));
(orderLine == orderLine2) // TRUEreturn (orderLine);
}
}
Persistence
Multiple retrievals of the same object return referenc
15
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
16
Persistence Context Propagation
@Stateless public class ShoppingCartBean implements ShoppingCart {
@EJB InventoryService inv;@EJB OrderService ord;
public void checkout(Item i, Product p) {inv.createOrder(item);ord.updateInventory(Product p)
}}
Persistence context
17
Persistence Context Propagation
@Stateless public class OrderServiceBean implements OrderService {
@PersistenceContext EntityManager em1;public void createOrder(Item item) {
em1.persist(new Order(item));
}}@Stateless public class InventoryServiceBean implements
InventoryService {@PersistenceContext EntityManager em2;
public void updateInventory(Product p) {Product product = em2.merge(p);. . .
}
18
Declarative Transaction Management Example
TX_REQUIRED TX_REQUIRED
TX_REQUIRED
PC PC
PC
ShoppingCart
InventoryService
OrderService
Check Out
1. UpdateInventory
New PersistenceContext
Persistence ContextPropagated
TransactionAttributes
2. Create Order
19
AuditServiceBean
@Statelesspublic class AuditServiceBean implements AuditService {
@PersistenceContextprivate EntityManager em;
@TransactionAttribute(REQUIRES_NEW)public void logTransaction2(int id, String action) {
LogRecord lr = new LogRecord(id, action);em.persist(lr);
}
NEWPC !
20
Declarative Transaction Management Example 2
REQUIRED REQUIRED
REQUIRES_NEW
PC PC
PC2
ShoppingCart
InventoryService
AuditService
Check Out
1. UpdateInventory
New PersistenceContext
Persistence ContextPropagated
TransactionAttributes
2. log transaction
NEWPC !
21
Persistence Provider PC Transaction Features
• Attribute-level change tracking• Only the minimal updates are sent to the database• Orders INSERT, UPDATE and DELETE statements• Minimizes database interactions• EntityManager flush SQL prior to commit
22
Persistence ContextManaged
Entity
DetachedEntity
Conversation with detached entity
ManagedEntity
ManagedEntity
Persistence ContextManaged
EntityManagedEntity
ManagedEntity
DetachedEntity
merge()
transaction-scopedpersistence context
request responserequestresponse
Conversation
transaction-scopedpersistence context
23
Conversation with detached entity@Stateless public ShoppingCartBean implements ShoppingCart {@PersistenceContext EntityManager entityManager;
public OrderLine createOrderLine(Product product,Order order) {OrderLine orderLine = new OrderLine(order, product);entityManager.persist(orderLine);return (orderLine);
}
public OrderLine updateOrderLine(OrderLine orderLine)OrderLine orderLine2 =entityManager.merge(orderLine));return orderLine2;}
}
Managed entity
Detached entity
Managed entity
24
Types of Persistence Context
• Persistence Context> lifetime maybe transaction-scoped or extended
• Transaction-scoped persistence context• Extended persistence context
> spans multiple transactions
25
Persistence Context
ManagedEntity
Conversation with Exented Persistence Context
ManagedEntity
ManagedEntity
request responserequestresponse
Conversation
extendedpersistence context
26
Extended Persistence Context@Stateful public class OrderMgr {
//Specify that we want an EXTENDED@PersistenceContext(type=PersistenceContextType.EXTENDED
EntityManager em;
//Cached orderprivate Order order;
//create and cache orderpublic void createOrder(String itemId) {
//order remains managed for the lifetime of the beaOrder order = new Order(cust);
em.persist(order);}
public void addLineItem(OrderLineItem li){order.lineItems.add(li);
}Managed entity
Managed entity
27
Extended Persistence Context@Stateful public class DeptMgr {
@PersistenceContext(type=PersistenceContextType.EXTENDEDEntityManager em;
private Department dept;
@TransactionAttribute(NOT_SUPPORTED)public void getDepartment(int deptId) {
dept = em.find(Department.class,deptId);}
@TransactionAttribute(NOT_SUPPORTED)public void addEmployee(int empId){
emp = em.find(Employee.class,empId);dept.getEmployees().add(emp);emp.setDepartment(dept);
}@Remove@TransactionAttribute(REQUIRES_NEW)
public void endUpdate(int deptId) {dept = em.find(Department.class,deptId);
}
28
Persistence Context-Transactional vs. Extended@Stateless
public class OrderMgr implements OrderService {
@PersistenceContext EntityManager em;public void addLineItem(OrderLineItem li){// First, look up the order.Order order = em.find(Order.class, orderID);order.lineItems.add(li);
}
@Stateful
public class OrderMgr implements OrderService {
@PersistenceContext(type = PersistenceContextType.EXTENDED))EntityManager em;// Order is cachedOrder orderpublic void addLineItem(OrderLineItem li){
// No em.find invoked for the order object
order.lineItems.add(li);}
look up the order
No em.find invoked
Managed entity
29
Persistence Context Micro Benchmark
Extended0%
20%
40%
60%
80%
100%
120%
tx/sec
Source: Internal benchmarks
• Micro benchmark with lots of lookups• Persistence context is caching entities
30
SEAM Conversations@Name("shopper")
@Scope(CONVERSATION)public class BookingManager {
@In EntityManager entityManager;
private Booking booking;
@Begin public void selectHotel(Hotel selectedHotel){
hotel = em.merge(selectedHotel);
}
@End public void confirm() {
em.persist(booking);
}
}
SEAM injected
SEAM conversation
31
Concurrency and Persistence Context
Persistence Context 1
Entity Manager
Persistence Context 2
Entity Manager
Data source
same entity
Object Identityonly one manage entityin PC represents a row
User 2 transactionUser 1 transaction
32
Optimistic versus Pessimistic Concurrency
• Optimistic Concurrency> Pros—No database locks held> Cons—Requires a version attribute in schema
� user or app must refresh and retry failed updates
> Suitable when application has few parallel updates• Pessimistic Concurrency
> Lock the row when data is read in� database locks the row upon a select� (SELECT . . . FOR UPDATE [NOWAIT])
> Pros—Simpler application code> Cons—Database locks
� limits concurrent access to the data = scalability� May cause deadlocks� Not in JPA 1.0 (vendor specific), supported in JPA 2.0
> Suitable when application has many parallel updates
33
Preventing Parallel Updatesuse @Version for optimistic locking
Used by persistence manager , Results in following SQL “UPDATE Employee SET ..., version = version + 1
WHERE id = ? AND version = readVersion”
Version Updated when transaction commits, merged or acquiring a write lock
OptimisticLockException if mismatch
Not used by the application!
public class Employee {@ID int id;@Version int version;...
Can be int, Integer, short
34
Preventing Parallel Updates – 1
tx1.begin();//Joe's employee id is 5//e1.version == 1e1 = findPartTimeEmp(5);
//Joe's current rate is $9e1.raise(2);
tx1.commit();//e1.version == 2 in db
//Joe's rate is $11
tx2.begin();//Joe's employee id is 5//e1.version == 1e1 = findPartTimeEmp(5);
//Joe's current rate is $9if(e1.getRate() < 10)
e1.raise(5);
//e1.version == 1 in db?tx2.commit();//Joe's rate is $14//OptimisticLockException
Time
35
Preventing Stale Data JPA 1.0
• Perform read or write locks on entities• Prevents non-repeatable reads in JPA
entityManager.lock( entity, READ);perform a version check on entity before commit
OptimisticLockException if mismatch
entityManager.lock( entity, WRITE);perform a version check on entity
OptimisticLockException if mismatchand increment version before commit
36
Preventing Stale Data
tx1.begin();d1 = findDepartment(dId);
//d1's original name is//”Engrg”d1.setName(“MarketEngrg”);
tx1.commit();
tx2.begin();
e1 = findEmp(eId);d1 = e1.getDepartment();em.lock(d1, READ);if(d1's name is “Engrg”)
e1.raiseByTenPercent();
//Check d1.version in dbtx2.commit();//e1 gets the raise he does//not deserve//Transaction rolls back
Time
37
Write lock prevents parallel updates
tx1.begin();d1 = findDepartment(dId);
//d1's original name is//”Engrg”d1.setName(“MarketEngrg”);
tx1.commit();//tx rolls back
tx2.begin();
e1 = findEmp(eId);d1 = e1.getDepartment();em.lock(d1, WRITE);
//version++ for d1em.flush();if(d1's name is “Engrg”)
e1.raiseByTenPercent();
tx2.commit();
Preventing Parallel Updates – 2
Time
38
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 5e1 = findPartTimeEmp(id); //Joe's current rate is $9
//Double every employee's salaryem.createQuery(
“Update Employee set rate = rate * 2”).executeUpdate();
//Joe's rate is still $9 in this persistence contextif(e1.getRate() < 10)
e1.raiseByFiveDollar();
tx.commit();//Joe's salary will be $14
39
JPA 2.0 Locks
• JPA1.0 only supported optimistic locking, JPA 2.0 also supports pessimistic locks
• JPA 2.0 LockMode values :> OPTIMISTIC (= READ)> OPTIMISTIC_FORCE_INCREMENT (= WRITE)> PESSIMISTIC> PESSIMISTIC_FORCE_INCREMENT
• Multiple places to specify lock
database locks the row(SELECT . . . FOR UPDATE )
40
//Read then lock:
Account acct = em.find(Account.class, acctId);
// Decide to withdraw $100 so lock it for update
em.lock(acct, PESSIMISTIC);
int balance = acct.getBalance();
acct.setBalance(balance - 100);
//Read and lock:
Account acct = em.find(Account.class,acctId,PESSIMISTIC);
// Decide to withdraw $100 (already locked)
int balance = acct.getBalance();
acct.setBalance(balance - 100);
JPA 2.0 Locking
Locks longer,could causebottlenecks,
deadlock
Lock after read, risk stale, could cause OptException
41
// read then lock and refresh
Account acct = em.find(Account.class, acctId);
// Decide to withdraw $100 - lock and refresh
em.refresh(acct, PESSIMISTIC);
int balance = acct.getBalance();
acct.setBalance(balance - 100);
JPA 2.0 Locking
“right” approach depends on requirements
�Trade-offs:�lock earlier : risk bad scalability, deadlock�Lock later : risk stale data for update, get optimistic lock exception
42
L2 cache shared across transactions and users
Putting it all together
User Session User Session User Session
Persistence Context(EntityManager)
Persistence Context(EntityManager)
Persistence Context(EntityManager)
L2 Cache(Shared Cache)
Entity managers for a specific PersistenceUnit on a given Java Virtual Machine (JVM™)
(EntityManagerFactory)
43
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)
44
L2 Cache
User transaction 1
Persistence Context
User transaction 2
Persistence Context
Data source
same entitynot shared
L2 Cache
Entity Entity
query that looks for a single object based on Id will go 1st to PC then to L2 cache, other q
Shared entity
45
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
46
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
47
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 IdentityMappublic boolean contains(Class class, Object pk);// invalidates object in the IdentityMappublic 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
}
48
EclipseLink Caching Architecture
EntityManager EntityManagerFactory
Server
L1 Cache
PC Cache
L2 Shared Cache Cache CoordinationJMS (MDB)RMICORBAIIOP
EclipseLink caches Entiti
49
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
50
@Entity@Table(name="EMPLOYEE")@Cache (
type=CacheType.WEAK,isolated=false,expiry=600000,alwaysRefresh=true,disableHits=true,coordinationType=INVALIDATE_CHANGED_OBJECTS)
public class Employee implements Serializable {...
}
EclipseLink Mapping Extensions Type=
Full: objects never flushed unweak: object will be garbage
@Cache� type, size,isolated, expiry, refresh, cache usage,� Cache usage and refresh query hints
=truedisables L2 cache
51
Hibernate L2 Cache• Hibernate L2 cache is not configured by default• Hibernate L2 does not cache Entities. Hibernate caches Id and state• Hibernate L2 cache is pluggable
> EHCache, OSCache, SwarmCacheProvider (JVM)> JBoss TreeCache Cluster> Can plug in others like Terracotta
Cache Concurrency Strategy
52
Hibernate L2 Cache<!-- optional configuration file parameter -->net.sf.ehcache.configurationResourceName=/name_of_configuration_resource
@Entity@Cache(usage = CacheConcurrencyStrategy.NONSTRICT_READ_WRITpublic Class Country {
private String name;...
}
not configured by default
Cache Concurrency Strategymust be supported by cache provider
53
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 { ... }
54
Agenda
>Entity Manager>Persistence Context>Entities>Schema and Queries>Transaction
55
Maintaining Relationship• Application bears the responsibility of maintaining
relationship between objects
Department AEmployee1
Employee2
Employee3
Employee1
Employee2
Employee3
Before After
Inconsistent!
Department B
Department A
Department B
deptA.getEmployees().add(e3);
56
Example – Domain Model
@Entity public class Employee {@Id private int id;private String firstName;private String lastName;@ManyToOne(fetch=LAZY)private Department dept;
...}@Entity public class Department {
@Id private int id;private String name;@OneToMany(mappedBy = "dept", fetch=LAZY)private Collection<Employee> emps = new ...;
...}
57
Example – Managing Relationship
public int addNewEmployee(...) {Employee e = new Employee(...);Department d = new Department(1, ...);
e.setDepartment(d);//Reverse relationship is not setem.persist(e);em.persist(d);
return d.getEmployees().size();}
INCORRECT
58
Example – Managing Relationship
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();}
CORRECT
59
Navigating RelationshipsData fetching strategy• EAGER – immediate• LAZY – loaded only when needed• LAZY is good for large objects and/or with
relationships with deep hierarchies
60
Lazy loading and JPA
• Default FetchType is LAZY for 1:m and m:n relationships> benefits large objects and relationships with deep hierarchies
• However for use cases where data is needed can cause n+1 selects
• LAZY – N + 1 problem:
@Entity public class Department {@Id private int id;@OneToMany(mappedBy = "dept")private Collection<Employee> emps ;
...}
SELECT d.id, ... FROM Department d // 1 timeSELECT e.id, ... FROM Employee e
WHERE e.deptId = ? // N times
61
Lazy loading and JPA
• Relationship can be Loaded Eagerly> But if you have several related relationships, could load too much !
OR
• Temporarily override the LAZY fetch type, use Join Fetch in a query:
@Entity public class Department {@Id private int id;@OneToMany(mappedBy = "dept", fetch=EAGER)private Collection<Employee> employees ;
...}
@NamedQueries({ @NamedQuery(name="getItEarly",query="SELECT d FROM Department d JOIN FETCH d.employees")})
public class Department{.....}
Can cause Cartesian product
62
Lazy loading and JPA• Capture generated SQL
> persistence.xml file:<property name="toplink.logging.level" value="FINE">
• Test run use cases and examine the SQL statements> optimise the number of SQL statements executed!> only retrieve the data your application needs!
• Lazy load large (eg BLOB) attributes and relationships that are not used often
• Override to Eagerly load in use cases where needed
63
Navigating Relationships
• Accessing a LAZY relationship from a detached entity> If not loaded , Causes an exception
• Solutions:> Use JOIN FETCH> Or Set Fetch type to EAGER> Or Access the collection before entity is detached:
d.getEmployees().size();
DetachedEntity
PersistenceContext
ManagedEntity
64
Navigating RelationshipsData 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
65
Using Cascade@Entity public class Employee {
@Id private int id;private String firstName;private String lastName;@ManyToOne(cascade=ALL, fetch=LAZY)private Department dept;
...}@Entity public class Department {
@Id private int id;private String name;@OneToMany(mappedBy = "dept"
cascade=ALL, fetch=LAZY)private Collection<Employee> emps = new ...;@OneToManyprivate Collection<DepartmentCode> codes;
...}
Employee
Department
DepartmentCode
cascade=ALL
X
66
Agenda
>Entity Manager>Persistence Context>Entities>Schema and Queries>Transaction
67
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
68
Normalization
• Normalization Eliminates redundant data> updates are usually faster.
� there's less data to change.
• However Normalized database causes joinsfor queries> Queries maybe slower> Normalize then maybe De-normalize
frequently read columns and cache them
69
Mapping Inheritance Hierarchies
Employee---------------------------
int idString firstNameString lastNameDepartment dept
PartTimeEmployee------------------------
int rate
FullTimeEmployee-----------------------
double salary
70
Single Table Per ClassBenefits• Simple• No joins required
> can be fast for Queries
Drawbacks• Not normalized
> Wastes space
• Requires columns corresponding to subclasses' state to be null
• Table can have too many columns> Larger tables= more data, can have
negative affects on performance
@Inheritance(strategy=SINGLE_TABLE)
EMPLOYEE---------------------------
ID IFIRSTNAME varchar(25LASTNAME varchar(25DEPT_ID int FK,RATE int NULL,SALARY double NUDISCRIM varchar(30
71
Joined SubclassBenefits• Normalized database
> Better for storage
• Database view same as domain model
• Easy to evolve domain modelDrawbacks• Queries cause joins
> Slower queries> Poor performance for deep
hierarchies, polymorphic queries and relationships
@Inheritance(strategy=JOINED)
ID int PK,FIRSTNAME varchar(255),LASTNAME varchar(255),DEPT_ID int FK,
ID int PK FRATE int NULL
ID int PK FSALARY double NULL
EMPLOYEE
PARTTIMEEMPLOYEE
FULLTIMEEMPLOYEE
72
Table Per ClassBenefits• No need for joins to read
entities of same type> Faster reads
Drawbacks• Not normalized
> Wastes space
• Polymorphic queries cause union (all employees)> Poor performance
• This strategy is not mandatory
@Inheritance(strategy=TABLE_PER_CLASS)
ID intFIRSTNAME varchar(255),LASTNAME varchar(255),DEPT_ID int FK,SALARY double NULL
ID int PFIRSTNAME varchar(255),LASTNAME varchar(255),DEPT_ID int FK,RATE int NULL
PARTTIMEEMPLOYEE
FULLTIMEEMPLOYEE
73
vertical partitioning
• limit number of columns per table• split large, infrequently used columns into a separate table
CREATE TABLE Customer (user_id INT NOT NULL AUTO_INCREMENT
, email VARCHAR(80) NOT NULL, display_name VARCHAR(50) NOT NULL, password CHAR(41) NOT NULL, first_name VARCHAR(25) NOT NULL, last_name VARCHAR(25) NOT NULL, address VARCHAR(80) NOT NULL, city VARCHAR(30) NOT NULL, province CHAR(2) NOT NULL, postcode CHAR(7) NOT NULL, interests TEXT NULL, bio TEXT NULL, signature TEXT NULL, skills TEXT NULL, PRIMARY KEY (user_id), UNIQUE INDEX (email)) ENGINE=InnoDB;
CREATE TABLE Customer (user_id INT NOT NULL AUTO_INCREMENT
, email VARCHAR(80) NOT NULL, display_name VARCHAR(50) NOT NULL, password CHAR(41) NOT NULL, first_name VARCHAR(25) NOT NULL, last_name VARCHAR(25) NOT NULL, address VARCHAR(80) NOT NULL, city VARCHAR(30) NOT NULL, province CHAR(2) NOT NULL, postcode CHAR(7) NOT NULL, interests TEXT NULL, bio TEXT NULL, signature TEXT NULL, skills TEXT NULL, PRIMARY KEY (user_id), UNIQUE INDEX (email)) ENGINE=InnoDB;
Less Frequentlyreferenced,TEXT data
Frequentlyreferenced
CREATE TABLE Customer(
user_id INT NOT NULL AUTO_INCREMENT
, email VARCHAR(80) NOT NULL
, display_name VARCHAR(50) NOT NULL
, password CHAR(41) NOT NULL
, PRIMARY KEY (user_id)
, UNIQUE INDEX (email)
) ENGINE=InnoDB;
CREATE TABLECREATE TABLE CustomerInfo (
user_id INT NOT NULL
, first_name VARCHAR(25) NOT NULL
, last_name VARCHAR(25) NOT NULL
, address VARCHAR(80) NOT NULL
, city VARCHAR(30) NOT NULL
, province CHAR(2) NOT NULL
, postcode CHAR(7) NOT NULL
, interests TEXT NULL, bio TEXT NULL, signature TEXT NULL, skills TEXT NULL, PRIMARY KEY (user_id)
, FULLTEXT KEY (interests, skills)
) ENGINE=MyISAM;
74
Vertical partitioning@Entitypublic class Customer {
int userid;String email;String password;@OneToOne(fetch=LAZY)CustomerInfo info;
}
@Entitypublic class CustomerInfo {
int userid;String name;String interests;@OneToOne(mappedBy=
"CustomerInfo")Customer customer;
}
> split large, infrequently used columns into a separate table
75
Scalability: Sharding - Application Partitioning
Cust_id 1-999
Cust_id 1000-1999
Cust_id 2000-2999
Web/AppServers
Sharding Architecture
> Sharding =Horizontal partitioning� Split table by rows into partitions
76
Know what SQL is executed• Capture generated SQL:
persistence.xml file:<property name="toplink.logging.level" value="FINE">
• Find and fix problem SQL:> Watch for slow Queries
� use the MySQL slow query log and use Explain– Can reveal problems such as a missing Indexes
> Watch for Queries that execute too often to load needed data> Watch for loading more data than needed
77
MySQL Query Analyser
Find and fix problem SQL:• how long a query took• results of EXPLAIN statements
• Historical and real-time analysis> query execution counts, run time
Its not just slow running queries that are a
78
Agenda
>Entities>Entity Manager>Persistence Context>Queries>Transaction
79
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
EntityManagerQuery query = em.createQuery(“select ...”);
> Beware of SQL injection, better to use with named parametersq = em.createQuery(“select e from Employee e WHERE ”
+ “e.empId LIKE '” + id + “'”);
q = em.createQuery(“select e from Employee e WHERE ”+ “e.empId LIKE ':id'”);
q.setParameter(“id”, id);
NOT GOOD
GOOD
80
Query Types – 2 • Native query
> Leverage the native database querying facilities> Not portable – ties queries to database
81
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 transactionOrder 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 visibleList list = q.getResultList();
82
Agenda
>Entities>Entity Manager>Persistence Context>Queries>Transaction
83
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)
8484
Carol McDonaldJava Architect
Dynamic,�typesafe�queries�in�JPA�2.0� How the Criteria API builds dynamic queries and reduces run-time failures The Java developer community has welcomed JPA since its introduction in 2006. The next major update of the specification — version 2.0 (JSR 317) — will be finalized later in 2009 (see Resources). One of the key features introduced in JPA 2.0 is the Criteria API, which brings a unique capability to the Java language: a way to develop queries that a Java compiler can verify for correctness at compile time. The Criteria API also includes mechanisms for building queries dynamically at run time. This article introduces the Criteria API and the closely associated metamodel concept. You will learn how to use the Criteria API to develop queries that a Java compiler can check for correctness to reduce run-time errors, in contrast to string-based Java Persistence Query Language (JPQL) queries. And through example queries that use database functions or match a template instance, I'll demonstrate the added power of programmatic query-construction mechanics compared to JPQL queries that use a predefined grammar. The article assumes you have a basic familiarity with Java language programming and common JPA usage such as EntityManagerFactory or EntityManager. What's wrong with this JPQL query? JPA 1.0 introduced JPQL, a powerful query language that's considered a major reason for JPA's popularity. However, JPQL — being a string-based query language with a definite grammar — has a few limitations. To understand one of the major limitations, consider the simple code fragment in Listing 1, which executes a JPQL query to select the list of Persons older than 20 years: Listing 1. A simple (and wrong) JPQL query EntityManager em = ...; String jpql = "select p from Person where p.age > 20"; Query query = em.createQuery(jpql); List result = query.getResultList(); This basic example shows the following key aspects of the query-execution model in JPA 1.0:
� A JPQL query is specified as a String (line 2). � EntityManager is the factory that constructs an executable query instance given a JPQL
string (line 3). � 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 doeOne of ththat are the Crite Listing 2EntityMQueryBuCriteriaQRoot<PePredicatc.where(cTypedQuList<Pers Listing 2
� L
� Infa
� InArerefo
� InarF F
es a typesafhe major advsyntacticallyriaQuery int
2. Basic steanager em =
uilder qb = eQuery<Persorson> p = c.
te condition condition); uery<Personson> result =
illustrates tine 1 obtain
n line 2, Entactory for Cr
n line 3, the A CriteriaQueesult this Cresult-type arorm one suc
n line 4, quere the core u
Figure 1 show
Figure 1. Int
fe query helvantages of ty incorrect. Lterface:
ps of writin= ... em.getQueryon> c = qb.cfrom(Person= qb.gt(p.ge
n> q = em.cr= q.getResul
the Criteria ns an EntityM
tityManager riteriaQuery.
QueryBuildery is geneririteriaQuery rguments —h asObject[]
ery expressiounits or nodws the hiera
terface hier
lp? the Criteria Listing 2 rew
ng a Criteria
yBuilder(); createQuery(n.class); t(Person_.ag
eateQuery(cltList();
API's core coManager ins
creates an i.
der factory coically typed. will return u
— from a pers — while co
ons are set odes that are aarchy of quer
rarchy of qu
API is that iwrites the JP
aQuery
(Person.class
ge), 20);
c);
onstructs anstance by on
instance of Q
onstructs a The genericupon executsistent entitynstructing a
on the Criterassembled inry expression
uery express
it prohibits tPQL query in
s);
nd demonstrne of the seve
QueryBuilde
CriteriaQuec type argumtion. You cay such as Pea CriteriaQu
riaQuery insn a tree to sns defined in
sions
the construcn Listing 1 u
rates its baseral availabl
er. QueryBui
ry instance.ment declarean supply vaerson.class t
uery.
tance. Querspecify a Critn the Criteri
ction of querusing
sic usage: le means.
ilder is the
s the type of
arious kinds to a more fre
ry expressionteriaQuery. ia API:
ries
f of ee-
ns
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.
� Line 5 constructs a Predicate. Predicate is another common form of query expression that evaluates to either true or false. A predicate is constructed by the QueryBuilder, which is the factory not only for CriteriaQuery, but also for query expressions. QueryBuilder has API methods for constructing all kinds of query expressions that are supported in traditional JPQL grammar, plus a few more. In Listing 2, QueryBuilder is used to construct an expression that evaluates whether the value of its first expression argument is numerically greater than the value of the second argument. The method signature is: Predicate gt(Expression<? extends Number> x, Number y); This method signature is a fine example of how a strongly typed language such as the Java language can be judiciously used to define an API that allows you to express what is correct and prohibits what is not. The method signature specifies that it is possible to compare an expression whose value is a Number only to another Number (and not, for example, to a String): Predicate condition = qb.gt(p.get(Person_.age), 20); But there is more to line 5. Notice the qb.gt() method's first input argument: p.get(Person_.age), where p is theRoot<Person> expression obtained previously. p.get(Person_.age) is a path expression. A path expression is the result of navigation from a root expression via one or more persistent attribute(s). Hence p.get(Person_.age)denotes a path expression by navigating from the root expression p by the age attribute of Person. You may wonder what Person_.age is. For the time being, assume it is a way to denote the age attribute of Person. I'll elaborate on the meaning of Person_.age when I discuss the new Metamodel API introduced in JPA 2.0. As I mentioned earlier, every query expression is generically typed to denote the type of the value the expression evaluates to. The path expression p.get(Person_.age) evaluates to an Integer if the age attribute in Person.classis declared to be of type Integer (or int). Because of the type safety inherent in the API, the compiler itself will raise an error for a meaningless comparison, such as: Predicate condition = qb.gt(p.get(Person_.age, "xyz"));
� Line 6 sets the predicate on the CriteriaQuery as its WHERE clause. � In line 7, EntityManager creates an executable query given an input CriteriaQuery. This
is similar to constructing an executable query given a JPQL string as input. But because the input CriteriaQuery carries richer type information, the result is a TypedQuery that is an extension of the familiar javax.persistence.Query. The TypedQuery, as the name suggests, knows the type it returns as a result of its execution. It is defined as: public interface TypedQuery<T> extends Query { List<T> getResultList(); }
ApuLi} Nco
� Inqusaof
To summ� C
suF F
� T
� Q
� Cso
As opposed toublic interfaist getResult
Naturally, theonstruction n line 8, the uery is finalaves the devf ClassCastE
marize the baCriteriaQueryuch as FROM
Figure 2 show
Figure 2. Cri
he query expo Root<o Predic
declaro Path<
a RooQueryBuilder
CriteriaQueryo that the el
o correspondace Query { tList();
e TypedQuerof the inputtype informly executed
veloper of troException er
asic aspects y is a tree ofM, WHERE, ws the claus
iteriaQuery
pressions arT>, which is
cate, which ered as interfT>, which dt<?> expressr is the facto
y is transferrlements of th
ding untype
ry result hastCriteriaQue
mation that isto get a list
ouble of an error at run ti
of the simpf query-expreandORDER
ses related to
y encapsulat
re genericallys equivalent evaluates toface Predicatdenotes a persion. Root<Tory for Criter
red to an exhe selected l
d super-inte
s the same Pery by a Ques carried throf results. T
extra (and ofime) while it
le example iession nodes
R BY in a trao a query:
tes the clau
y typed. A feto a FROM a Boolean vte extends Ersistent attriT> is a speciriaQuery and
ecutable qulist can be a
erface:
Person.classeryBuilder (liroughout shThe result isften ugly) caterating thro
in Listing 2: s that are u
aditional stri
uses of a tra
ew typical exclause. value of true
Expression<Bibute navigaialPath<T> wd query exp
ery with its accessed with
s type specifiine 3). ows its adva a typed list
ast (and minough the res
sed to speciing-based qu
aditional qu
xpressions a
e or false. (InBoolean>.) ated from with no pareressions of a
type informhout any run
fied during th
antage whent of Persons nimizes the rsultant eleme
fy query clauuery languag
uery
are:
n fact, it is
nt. all sorts.
ation presern-time casti
he
n the that
risk ents.
uses ge.
rved ing.
Metamodel of a persistent domain The discussion of Listing 2 points out an unusual construct: Person_.age, which is a designation for the persistent ageattribute of Person. Listing 2 uses Person_.age to form a path expression navigating from a Root<Person> expression p byp.get(Person_.age). Person_.age is a public static field in the Person_ class, and Person_ is the static, instantiated, canonical metamodel class corresponding to the original Person entity class. A metamodel class describes the meta information of a persistent class. A metamodel class is canonical if the class describes the meta information of a persistent entity in the exact manner stipulated by the JPA 2.0 specification. A canonical metamodel class is static in the sense all its member variables are declared static (and public). The Person_.age is one such static member variable. You instantiate the canonical class by generating a concrete Person_.java at a source-code level at development time. Through such instantiation, it is possible to refer to persistent attributes of Person at compile time, rather than at run time, in a strongly typed manner. This Person_ metamodel class is an alternative means of referring to meta information of Person. This alternative is similar to the much-used (some may say, abused) Java Reflection API, but with a major conceptual difference. You can use reflection to obtain the meta information about an instance of a java.lang.Class, but meta information about Person.class cannot be referred to in a way that a compiler can verify. For example, using reflection, you'd refer to the field named age in Person.classwith: Field field = Person.class.getField("age"); However, this technique is fraught with a limitation similar to the one you observed in the case of the string-based JPQL query inListing 1. The compiler feels happy about this piece of code but cannot verify whether it will work. The code can fail at run time if it includes even a simple typo. Reflection will not work for what JPA 2.0's typesafe query API wants to accomplish. A typesafe query API must enable your code to refer to the persistent attribute named age in a Person class in a way that a compiler can verify at compile time. The solution that JPA 2.0 provides is the ability to instantiate a metamodel class namedPerson_ that corresponds to Person by exposing the same persistent attributes statically. Any discussion about meta or meta-meta information often induces somnolence. So I'll present a concrete example of a metamodel class for a familiar Plain Old Java Object (POJO) entity class — domain.Person, shown in Listing 3: Listing 3. A simple persistent entity package domain; @Entity public class Person { @Id private long ssn; private string name; private int age; // public gettter/setter methods public String getName() {...} } This is a typical definition of a POJO, with annotations — such as @Entity or @Id — that enable a JPA provider to manage instances of this class as persistent entities. The corresponding static canonical metamodel class of domain.Person is shown in Listing 4:
Listing 4. Canonical metamodel for a simple entity package domain; import javax.persistence.metamodel.SingularAttribute; @javax.persistence.metamodel.StaticMetamodel(domain.Person.class) public class Person_ { public static volatile SingularAttribute<Person,Long> ssn; public static volatile SingularAttribute<Person,String> name; public static volatile SingularAttribute<Person,Integer> age; } The metamodel class declares each persistent attribute of the original domain.Person entity as a static public field ofSingularAttribute<Person,?> type. Making use of this Person_ metamodel class, I can refer to the persistent attribute ofdomain.Person named age — not via the Reflection API, but as a direct reference to the static Person_.age field — at compile time. The compiler can then enforce type checking based on the declared type of the attribute named age. I've already cited an example of such a restriction: QueryBuilder.gt(p.get(Person_.age), "xyz") will cause a compiler error because the compiler can determine from the signature of QueryBuilder.gt(..) and type of Person_.age that a Person's age is a numeric field and cannot be compared against a String. A few other key points to notice are:
� The metamodel Person_.age field is declared to be of type javax.persistence.metamodel.SingularAttribute. SingularAttribute is one of the interfaces defined in the JPA Metamodel API, which I'll describe in the next section. The generic type arguments of a SingularAttribute<Person, Integer> denote the class that declares the original persistent attribute and the type of the persistent attribute itself.
� The metamodel class is annotated as @StaticMetamodel(domain.Person.class) to designate it as a metamodel class corresponding to the original persistent domain.Person entity.
The Metamodel API I've defined a metamodel class as a description of a persistent entity class. Just as the Reflection API requires other interfaces — such as java.lang.reflect.Field or java.lang.reflect.Method — to describe the constituents ofjava.lang.Class, so the JPA Metamodel API requires other interfaces, such as SingularAttribute, PluralAttribute, to describe a metamodel class's types and their attributes. Figure 3 shows the interfaces defined in the Metamodel API to describe types:
Figure 3
Figure 4 Figure 4
The interAPI. Thisexample,distinctioan interfathat is novia two s The JavapioneerinawarenesJPA Metaexample,and Emb
3. Interface
shows the i
4. Interface
rfaces of JPAs finer distin, the Java Reon is made vface. Of courot the same eparate defi
a Reflection Ang concept ass of the useamodel API h, persistent ebeddable. Be
hierarchy f
nterfaces de
hierarchy o
A's Metamodnction is requeflection APIvia separate rse, you can as represen
initions.
API was intrat that time fe and power harnesses thentities are sefore JPA 2.0
for persisten
efined in the
of persisten
del API are muired to exprI represents definitions aask a Class
nting the con
roduced at thfor a commoof strongly
hat power tosemantically0, this sema
nt types in
Metamodel
nt attributes
more specialiress rich meall Java typ
among concs whether it ncept of inter
he inceptionon general-ptyped system
o introduce sy distinguish
antic distinct
the Metam
API to desc
s in the Met
ized than theta informatipes asjava.lacepts such ais an interfarface differe
n of the Javapurpose progms has progstrong typinhed as Mapption was rep
model API
ribe attribut
tamodel AP
hose of the Jaion about pe
ang.Class. Thas class, abstace or if it is ntly from an
a language (agramming lagressed over ng for persistpedSuperClapresented via
tes:
PI
ava Reflectioersistence. Fhat is, no sptract class, aabstract —
n abstract cl
and was quianguage), bu
the years. Ttent entities.ass, Entity, a correspond
on For pecial and but
lass
ite a ut The . For
ding
class-leveseparate thejavax.Similarlyas Singu Aside froadvantagYou've sewhen I d Run-timBroadly sReflectionpersistenneeded fobyjava.lamust all the sensewhich is dreadedCdeveloper This noti1.0 as a penumeramade avathe javaxall persis Figure 5
This inteclass. Foentity, yoEntityMaMetamodEntityTyp This is anvia ClassClassLoaClass<?>
el annotatiointerfaces —
.persistencey, the persistlarAttribute
om the aesthges that helpeen some of escribe exam
me scope speaking, onn API and thnce metadataor the metam
ang.ClassLoabe defined ue that if a clnot under t
ClassNotFour or deploye
ion of run-tipersistence
ated in the <ailable to thex.persistencestent entities
5. Metamode
erface lets thor example, tou can writeanagerFactordel metamodpe<Person>
nalogous, wsLoader: ader classloa> clazz = clas
ns in the pe— MappedSu.metamodel tent attribut, CollectionA
hetics of descp to build typthese advan
mples of join
ne can draw he interfacesa. To furthermodel interfaader at run tunder the scass A definehe scope of
undExceptionr for environ
me scope asunit. The scoclass> clause developer e.metamodels known to a
el interface
he metamodeto obtain a re: ry emf = ...;
del = emf.getpClass = me
with slightly d
ader = Threassloader.load
ersistent-clasuperclassTyppackage to
tes are distinAttribute, an
cription, thepesafe querintages in thens using Crit
some paralls ofjavax.perr the analogfaces. The javtime. A set ocope of a Claed under theClassLoadern or NoClassnments with
s a strict set ope of a persse of a METAat run time l.Metamodela specific pe
e is the cont
el elements breference to t
tMetamodel(etamodel.en
different styl
ad.currentThdClass("dom
ss definitionpe, EntityTybring their s
nguished at ndMapAttrib
ese specializeies and redue earlier examteriaQuery.
lels betweenrsistence.megy, an equivava.lang.Clasof Java classassLoader. Te scope ofClar L, the resusDef FoundE
h multiple Cl
of mutuallysistence uniA-INF/persisvia linterface. Trsistence un
tainer of ty
be accessed the persisten
); ntity(Person.c
le and idiom
hread().getCmain.Person"
n. JPA Metamype, and Emsemantic sptype-definit
bute.
ed metamoduce the chanmples, and y
n the traditioetamodel spealent concepss instancess instances tThe set bounassLoader L ult is a Error (and olassLoaders)
y referable clit in terms ostence.xml fi
The Metamodnit, as illustr
ypes in a per
by their cornt metadata
class);
ms, to obtain
ContextClass);
model descrimbeddableTyppecialties inttion level via
del interfacesnce of run-timyou will see
onal interfacecialized to d
pt of run-tims are scoped that referencndaries are s
tries to refe
often sleep d).
lasses is capof its persistefile. In JPA 2
del interface rated in Figu
rsistence un
rresponding a for a Perso
ning a Class
sLoader();
ibes three pe — in o sharper fo
a interfaces s
s have practme errors. more of the
ces of the Jadescribe
me scope is
ce one anothstrict or closeer to class B,
deprivation fo
ptured in JPent entities i2.0, the scop
is the holdeure 5:
nit
persistent-en persistent
by its name
ocus. such
tical
em
ava
her ed in ,
or a
PA is
pe is
er of
entity t
e
EntityType<Person> can be browsed at run time to get the persistent attributes declared in the Person entity. If the application invokes a method on pClass such as pClass.getSingularAttribute("age", Integer.class), it will return aSingularAttribute<Person, Integer> instance that is effectively the same as the static Person_.age member of the instantiated canonical metamodel class. Essentially, the persistent attribute that the application can refer to at run time via the Metamodel API is made available to a Java compiler by instantiation of the static canonical metamodel Person_ class. Apart from resolving a persistent entity to its corresponding metamodel elements, the Metamodel API also allows access to all the known metamodel classes (Metamodel.getManagedTypes()) or access to a metamodel class by its persistence-specific information — for example embeddable(Address.class), which returns a EmbeddableType<Address> instance that is a subinterface of ManagedType<>. In JPA, the meta information about a POJO is further attributed with persistent specific meta information — such as whether a class is embedded or which fields are used as primary key — with source-code level annotations (or XML descriptors). The persistent meta information falls into two broad categories: for persistence (such as @Entity) and for mapping (such as@Table). In JPA 2.0, the metamodel captures the metadata only for persistence annotations — not for the mapping annotation. Hence, with the current version of the Metamodel API, it's possible to know which fields are persistent, but it's not possible to find out which database columns they are mapped to. Canonical vs. non-canonical Although the JPA 2.0 specification stipulates the exact shape of a canonical static metamodel class (including the metamodel class's fully qualified name and the names of its static fields), it is entirely possible for an application to write these metamodel classes as well. If the application developer writes the metamodel classes, they are called non-canonical metamodel. Currently, the specification for non-canonical metamodel is not very detailed, and support for non-canonical metamodel can be nonportable across the JPA providers. You may have noticed that the public static fields are only declared in canonical metamodel but not initialized. The declaration makes it possible to refer to these fields during development of aCriteriaQuery. But they must be assigned a value to be useful at run time. While it is the responsibility of the JPA provider to assign values to these fields for canonical metamodel, similar warranty is not extended for non-canonical metamodel. Applications that use non-canonical metamodel must either depend on specific vendor mechanisms or devise their own mechanics to initialize the field values to metamodel attributes at run time. Code generation and usability Automatic source-code generation often raises eyebrows. The case of generated source code for canonical metamodel adds some concerns. The generated classes are used during development, and other parts of the code that build the CriteriaQuerydirectly refer to them at compile time, leaving some usability questions:
� 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?
� Should the source-code files be checked in a version-controlled configuration-management system?
� How should the correspondence between an original Person entity definition and its canonical Person_ metamodel be maintained? For example, what if Person.java is edited to add an extra persistent attribute, or refactored to rename a persistent attribute?
The answers to these questions are not definitive at the time of this writing.
Annotation processing and metamodel generation Quite naturally, if you have many persistent entities you will not be inclined to write the metamodel classes yourself. The persistence provider is expected to generate these metamodel classes for you. The specification doesn't mandate such a facility or the generation mechanics, but an implicit understanding among JPA providers is that they'll generate the canonical metamodel using the Annotation Processor facility integrated in the Java 6 compiler. Apache OpenJPA provides a utility to generate these metamodel classes either implicitly when you compile the source code for persistent entities or by explicitly invoking a script. Prior to Java 6, an annotation processor tool called apt was available and widely used — but with Java 6, the coupling between compiler and Annotation Processor is defined as part of the standard. The process of generating these metamodel classes in OpenJPA as your persistence provider is as simple as compiling the POJO entity with OpenJPA class libraries in the compiler's classpath: $ javac domain/Person.java The canonical metamodel Person_ class will be generated, written in the same source directory as Person.java, and compiled as a side-effect of this compilation. Writing queries in a typesafe manner So far, I've established the components of CriteriaQuery and its associated metamodel classes. Now I'll show you how to develop some queries with the Criteria API. Functional expressions Functional expressions apply a function to one or more input arguments to create a new expression. The functional expression's type depends on the nature of the function and type of its arguments. The input arguments themselves can be expressions or literal values. The compiler's type-checking rules coupled with the API's signature govern what constitutes legitimate input. Consider a single-argument expression that applies averaging on its input expression. Listing 5 shows the CriteriaQuery to select the average balance of all Accounts: Listing 5. Functional expression in CriteriaQuery CriteriaQuery<Double> c = cb.createQuery(Double.class); Root<Account> a = c.from(Account.class); c.select(cb.avg(a.get(Account_.balance))); An equivalent JPQL query would be: String jpql = "select avg(a.balance) from Account a"; In Listing 5, the QueryBuilder factory (represented by the variable cb) creates an avg() expression and uses that expression in the query's select() clause. The query expression is a building block that can be assembled to define the final selection predicate for the query. The example in Listing 6 shows a Path expression created by navigating to the balance of Account, and then the Path expression is used as an input expression in a couple of binary functional expressions — greaterThan() and lessThan() — both of which result in a Boolean expression or simply a predicate. The predicates are then combined via an and() operation to form the final selection predicate to be evaluated by the query's where() clause: Fluent API
As this example shows, the Criteria API methods often return the type that can be directly used in a related method, thereby providing a popular programming style known as Fluent API.
Listing 6. where() predicate in CriteriaQuery CriteriaQuery<Account> c = cb.createQuery(Account.class); Root<Account> account = c.from(Account.class); Path<Integer> balance = account.get(Account_.balance); c.where(cb.and (cb.greaterThan(balance, 100), cb.lessThan(balance), 200))); An equivalent JPQL query would be: "select a from Account a where a.balance>100 and a.balance<200"; Complex predicates Certain expressions — such as in() — apply to a variable number of expressions. Listing 7 shows an example: Listing 7. Multivalued expression in CriteriaQuery CriteriaQuery<Account> c = cb.createQuery(Account.class); Root<Account> account = c.from(Account.class); Path<Person> owner = account.get(Account_.owner); Path<String> name = owner.get(Person_.name); c.where(cb.in(name).value("X").value("Y").value("Z")); This example navigates from Account via two steps to create a path expression representing the name of an account's owner. Then it creates an in() expression with the path expression as input. The in() expression evaluates if its input expression equals any of its variable number of arguments. These arguments are specified through the value() method on the In<T>expression, which has the following method signature: In<T> value(T value); Notice how Java generics are used to specify that an In<T> expression can be evaluated for membership only with values of type T. Because the path expression representing the Account owner's name is of type String, the only valid comparison is against String-valued arguments, which can be either a literal or another expression that evaluates to String. Contrast the query in Listing 7 with the equivalent (correct) JPQL: "select a from Account a where a.owner.name in ('X','Y','Z')"; A slight oversight in the JPQL will not only be undetected by the compiler but also will produce an unintended outcome. For example: "select a from Account a where a.owner.name in (X, Y, Z)";
Joining relationships Although the examples in Listing 6 and Listing 7 use expressions as the building blocks, the queries are based on a single entity and its attributes. But often queries involve more than one entity, which requires you to join two or more entities.CriteriaQuery expresses joining two entities by typed join expressions. A typed join expression has two type parameters: the type you are joining from and the bindable type of the attribute being joined. For example, if you want to query for the Customers whose one or more PurchaseOrder(s) are not delivered yet, you need to express this by an expression that joins Customer toPurchaseOrders, where Customer has a persistent attribute named orders of type java.util.Set<PurchaseOrder>, as shown in Listing 8: Listing 8. Joining a multivalued attribute CriteriaQuery<Customer> q = cb.createQuery(Customer.class); Root<Customer> c = q.from(Customer.class); SetJoin<Customer, PurchaseOrder> o = c.join(Customer_.orders); The join expression created from the root expression c and the persistent Customer.orders attribute is parameterized by the source of join — that is, Customer — and the bindable type of the Customer.orders attribute, which is PurchaseOrder andnot the declared type java.util.Set<PurchaseOrder>. Also notice that because the original attribute is of typejava.util.Set, the resultant join expression is SetJoin, which is a specialized Join for an attribute of declared typejava.util.Set. Similarly, for other supported multivalued persistent attribute types, the API defines CollectionJoin,ListJoin, and MapJoin. (Figure 1 shows the various join expressions.) There is no need for an explicit cast in the third line inListing 8 because CriteriaQuery and the Metamodel API recognize and distinguish attribute types that are declared asjava.util.Collection or List or Set or Map by overloaded methods for join(). The joins are used in queries to form a predicate on the joined entity. So if you want to select the Customers with one or more undelivered PurchaseOrder(s), you can define a predicate by navigating from the joined expression o via its status attribute, comparing it with DELIVERED status, and negating the predicate as: Predicate p = cb.equal(o.get(PurchaseOrder_.status), Status.DELIVERED) .negate(); One noteworthy point about creating a join expression is that every time you join from an expression, it returns a new join expression, as shown in Listing 9: Listing 9. Every join creates a unique instance SetJoin<Customer, PurchaseOrder> o1 = c.join(Customer_.orders); SetJoin<Customer, PurchaseOrder> o2 = c.join(Customer_.orders); assert o1 == o2; The assertion in Listing 9 for equality of two join expressions from the same expression c with the same attribute will fail. Thus, if a query involves a predicate for PurchaseOrders that are not delivered and whose value is more than $200, then the correct construction is to join PurchaseOrder with the root Customer expression only once, assign the resultant join expression to a local variable (equivalent to a range variable in JPQL terminology), and use the local variable in forming the predicate.
Using parameters Take a look back at this article's original JPQL query (the correct one): String jpql = "select p from Person p where p.age > 20"; Though queries are often written with constant literals, it is not a good practice. The good practice is to parameterize a query, which allows the query to be parsed or prepared only once, cached, and reused. So a better way to write the query is to use a named parameter: String jpql = "select p from Person p where p.age > :age"; A parameterized query binds the value of the parameter before the query execution: Query query = em.createQuery(jpql).setParameter("age", 20); List result = query.getResultList(); In a JPQL query, the parameters are encoded in the query string as either named (preceded by a colon — for example, :age) or positional (preceded by a question mark — for example, ?3). In CriteriaQuery, the parameters themselves are query expressions. Like any other expression, they are strongly typed and constructed by the expression factory — namely,QueryBuilder. The query in Listing 2, then, can be parameterized as shown in Listing 10: Listing 10. Using parameters in a CriteriaQuery ParameterExpression<Integer> age = qb.parameter(Integer.class); Predicate condition = qb.gt(p.get(Person_.age), age); c.where(condition); TypedQuery<Person> q = em.createQuery(c); List<Person> result = q.setParameter(age, 20).getResultList(); To contrast the usage of parameters to that of JPQL: the parameter expression is created with explicit type information to be anInteger and is directly used to bind a value of 20 to the executable query. The extra type information is often useful for reducing run-time errors, because it prohibits the parameter from being compared against an expression of an incompatible type or being bound with a value of an inadmissible type. Neither form of compile-time safety is warranted for the parameters of a JPQL query. The example in Listing 10 shows an unnamed parameter expression that is directly used for binding. It is also possible to assign a name to the parameter as the second argument during its construction. In that case, you can bind the parameter value to the query using that name. What is not possible, however, is use of positional parameters. Integral position in a (linear) JPQL query string makes some intuitive sense, but the notion of an integral position cannot be carried forward in the context ofCriteriaQuery, where the conceptual model is a tree of query expressions. Another interesting aspect of JPA query parameters is that they do not have intrinsic value. A value is bound to a parameter in the context of an executable query. So it is perfectly legal to create two separate executable queries from the same CriteriaQueryand bind two different integer values to the same parameter for these executable queries.
Projecting the result You've seen that the type of result a CriteriaQuery will return upon execution is specified up front when a CriteriaQuery is constructed by QueryBuilder. The query's result is specified as one or more projection terms. There are two ways to specify the projection term on the CriteriaQuery interface: CriteriaQuery<T> select(Selection<? extends T> selection); CriteriaQuery<T> multiselect(Selection<?>... selections); The simplest and often used projection term is the candidate class of the query itself. It can be implicit, as shown in Listing 11: Listing 11. CriteriaQuery selects candidate extent by default CriteriaQuery<Account> q = cb.createQuery(Account.class); Root<Account> account = q.from(Account.class); List<Account> accounts = em.createQuery(q).getResultList(); In Listing 11, the query from Account does not explicitly specify its selection term and is the same as explicitly selecting the candidate class. Listing 12 shows a query that uses an explicit selection term: Listing 12. CriteriaQuery with explicit single selection term CriteriaQuery<Account> q = cb.createQuery(Account.class); Root<Account> account = q.from(Account.class); q.select(account); List<Account> accounts = em.createQuery(q).getResultList(); When the projected result of the query is something other than the candidate persistent entity itself, several other constructs are available to shape the result of the query. These constructs are available in the QueryBuilder interface, as shown in Listing 13: Listing 13. Methods to shape query result <Y> CompoundSelection<Y> construct(Class<Y> result, Selection<?>... terms); CompoundSelection<Object[]> array(Selection<?>... terms); CompoundSelection<Tuple> tuple(Selection<?>... terms); The methods in Listing 13 build a compound projection term composed of other selectable expressions. The construct()method creates an instance of the given class argument and invokes a constructor with values from the input selection terms. For example, if CustomerDetails — a nonpersistent entity — has a constructor that takes String and int arguments, then aCriteriaQuery can return CustomerDetails as its result by creating instances from name and age of selected Customer — a persistent entity — instances, as shown in Listing 14: Listing 14. Shaping query result into instances of a class by construct() CriteriaQuery<CustomerDetails> q = cb.createQuery(CustomerDetails.class); Root<Customer> c = q.from(Customer.class); q.select(cb.construct(CustomerDetails.class, c.get(Customer_.name), c.get(Customer_.age));
Multiple projection terms can also be combined into a compound term that represents an Object[] or Tuple. Listing 15 shows how to pack the result into an Object[]: Listing 15. Shaping query result into an Object[] CriteriaQuery<Object[]> q = cb.createQuery(Object[].class); Root<Customer> c = q.from(Customer.class); q.select(cb.array(c.get(Customer_.name), c.get(Customer_.age)); List<Object[]> result = em.createQuery(q).getResultList(); This query returns a result list in which each element is an Object[] of length 2, the zero-th array element is Customer's name, and the first element is Customer's age. Tuple is a JPA-defined interface to denote a row of data. A Tuple is conceptually a list of TupleElements — whereTupleElement is the atomic unit and the root of all query expressions. The values contained in a Tuple can be accessed by either a 0-based integer index (similar to the familiar JDBC result), an alias name of the TupleElement, or directly by theTupleElement. Listing 16 shows how to pack the result into a Tuple: Listing 16. Shaping query result into Tuple CriteriaQuery<Tuple> q = cb.createTupleQuery(); Root<Customer> c = q.from(Customer.class); TupleElement<String> tname = c.get(Customer_.name).alias("name"); q.select(cb.tuple(tname, c.get(Customer_.age).alias("age"); List<Tuple> result = em.createQuery(q).getResultList(); String name = result.get(0).get(name); String age = result.get(0).get(1); Limitations on nesting It is theoretically possible to compose complex result shapes by nesting terms such as a Tuple whose elements themselves are Object[]s or Tuples. However, the JPA 2.0 specification prohibits such nesting. The input terms of a multiselect() cannot be an array or tuple-valued compound term. The only compound terms allowed as multiselect()arguments are ones created by the construct()method (which essentially represent a single element). However, OpenJPA does not put any restriction on nesting one compound selection term inside another.
This query returns a result list each element of which is a Tuple. Each tuple, in turn, carries two elements — accessible either by index or by the alias, if any, of the individual TupleElements, or directly by the TupleElement. Two other noteworthy points in Listing 16 are the use of alias(), which is a way to attach a name to any query expression (creating a new copy as a side-effect), and acreateTupleQuery() method on QueryBuilder, which is merely an alternative to createQuery(Tuple.class). The behavior of these individual result-shaping methods and what is specified as the result type argument of the CriteriaQuery during construction are combined into the semantics of themultiselect() method. This method interprets its input terms based on the result type of the CriteriaQuery to arrive at the shape of the result. To construct CustomerDetails instances as in Listing 14 using multiselect(), you need to specify the CriteriaQueryto be of type CustomerDetails and simply invoke multiselect()with the terms that will compose the CustomerDetails constructor, as shown in Listing 17:
Listing 17. multiselect() interprets terms based on result type CriteriaQuery<CustomerDetails> q = cb.createQuery(CustomerDetails.class); Root<Customer> c = q.from(Customer.class); q.multiselect(c.get(Customer_.name), c.get(Customer_.age)); Because the query result type is CustomerDetails, multiselect() interprets its argument projection terms as the constructor argument to CustomerDetails. If the query were specified to return a Tuple, the multiselect() method with the exact same arguments would create Tuple instances instead, as shown in Listing 18: Listing 18. Creating Tuple instances with multiselect() CriteriaQuery<Tuple> q = cb.createTupleQuery(); Root<Customer> c = q.from(Customer.class); q.multiselect(c.get(Customer_.name), c.get(Customer_.age)); The behavior of multiselect() gets more interesting with Object as result type or if no type argument is specified. In such cases, if multiselect() is used with a single input term, then the return value is the selected term itself. But if multiselect()contains more than one input term, the result is an Object[].
Advanced features So far, I have mainly emphasized the strongly typed nature of the Criteria API and the fact that it helps to minimize syntactic errors that can creep into string-based JPQL queries. The Criteria API is also a mechanism for building queries programmatically and so is often referred to as a dynamic query API. The power of a programmable query construction API is limited only by the inventiveness of its user. I'll present four examples:
� Using a weakly typed version of the API to build dynamic queries � Using a database-supported function as a query expression to extend the grammar � Editing a query for search-within-result functionality � Query-by-example — a familiar pattern popularized by the object-database community
Weak typing and dynamic query building The Criteria API's strong type checking is based on the availability of instantiated metamodel classes at development time. However, for some use cases, the entities to be selected can only be determined at run time. To support such usage, the Criteria API methods provide a parallel version in which persistent attributes are referred by their names (similar to the Java Reflection API) rather than by reference to instantiated static metamodel attributes. This parallel version of the API can support truly dynamic query construction by sacrificing the type checking at compile time. Listing 19 rewrites the example in Listing 6using the weakly typed version: Listing 19. Weakly typed query Class<Account> cls = Class.forName("domain.Account"); Metamodel model = em.getMetamodel(); EntityType<Account> entity = model.entity(cls); CriteriaQuery<Account> c = cb.createQuery(cls); Root<Account> account = c.from(entity); Path<Integer> balance = account.<Integer>get("balance"); c.where(cb.and (cb.greaterThan(balance, 100), cb.lessThan(balance), 200)));
The weakly typed API, however, cannot return correct generically typed expressions, thereby generating a compiler warning for an unchecked cast. One way to get rid of these pesky warning messages is to use a relatively rare facility of Java generics: parameterized method invocation, as shown in Listing 19's invocation of the get() method to obtain a path expression. Extensible datastore expressions A distinct advantage of a dynamic query-construction mechanism is that the grammar is extensible. For example, you can use the function() method in the QueryBuilder interface to create an expression supported by the database: <T> Expression<T> function(String name, Class<T> type, Expression<?>...args); The function() method creates an expression of the given name and zero or more input expressions. The function()expression evaluates to the given type. This allows an application to create a query that evaluates a database function. For example, the MySQL database supports a CURRENT_USER() function that returns the user-name and host-name combination as a UTF-8 encoded string for the MySQL account that the server used to authenticate the current client. An application can use theCURRENT_USER() function, which takes no argument, in a CriteriaQuery, as Listing 20 demonstrates: Listing 20. Using a database-specific function in a CriteriaQuery CriteriaQuery<Tuple> q = cb.createTupleQuery(); Root<Customer> c = q.from(Customer.class); Expression<String> currentUser = cb.function("CURRENT_USER", String.class, (Expression<?>[])null); q.multiselect(currentUser, c.get(Customer_.balanceOwed)); Notice that an equivalent query is simply not possible to express in JPQL, because it has a defined grammar with a fixed number of supported expressions. A dynamic API is not strictly limited by a fixed set of expressions. Editable query A CriteriaQuery can be edited programmatically. The clauses of the query — such as its selection terms, the selection predicate in a WHERE clause, and ordering terms in an ORDER BY clause — can all be mutated. This editing capability can be used in a typical "search-within-result"-like facility whereby a query predicate is further refined in successive steps by adding more restrictions. The example in Listing 21 creates a query that orders its result by name and then edits the query to order also by ZIP code: Listing 21. Editing a CriteriaQuery CriteriaQuery<Person> c = cb.createQuery(Person.class); Root<Person> p = c.from(Person.class); c.orderBy(cb.asc(p.get(Person_.name))); List<Person> result = em.createQuery(c).getResultList(); // start editing List<Order> orders = c.getOrderList(); List<Order> newOrders = new ArrayList<Order>(orders); newOrders.add(cb.desc(p.get(Person_.zipcode))); c.orderBy(newOrders); List<Person> result2 = em.createQuery(c).getResultList();
In-memory evaluation in OpenJPA
With OpenJPA's extended features, the search-within-result example in Listing 21 can be made even more efficient by evaluating the edited query in-memory. This example dictates that the result of the edited query will be a strict subset of the original result. Because OpenJPA can evaluate a query in-memory when a candidate collection is specified, the only modification required is to the last line of Listing 21 to supply the result of the original query:
List<Person> result2 = em.createQuery(c).setCandidateCollection(result).getResultList();
The setter methods on CriteriaQuery — select(), where(), ororderBy() — erase the previous values and replace them with new arguments. The list returned by the corresponding getter methods such as getOrderList() is not live — that is, adding or removing elements on the returned list does not modify theCriteriaQuery; furthermore, some vendors may even return an immutable list to prohibit inadvertent usage. So a good practice is to copy the returned list into a new list before adding or removing new expressions. Query-by-example Another useful facility in a dynamic query API is that it can supportquery-by-example with relative ease. Query-by-example (developed by IBM® Research in 1970) is often cited as an early example of end-user usability for software. The idea of query-by-example is that instead of specifying the exact predicates for a query, a template instance is presented. Given the template instance, a conjunction of predicates — where each predicate is a comparison for a nonnull, nondefault attribute value of the template instance — is created. Execution of this query evaluates the predicate to find all instances that match the template instance. Query-by-example was considered for inclusion in the JPA 2.0 specification but is not included. OpenJPA supports this style of query through its extended OpenJPAQueryBuilder interface, as shown in Listing 22: Listing 22. Query-by-example using OpenJPA's extension of CriteriaQuery CriteriaQuery<Employee> q = cb.createQuery(Employee.class); Employee example = new Employee(); example.setSalary(10000); example.setRating(1); q.where(cb.qbe(q.from(Employee.class), example); As this example shows, OpenJPA's extension of the QueryBuilder interface supports the following expression: public <T> Predicate qbe(From<?, T> from, T template); This expression produces a conjunction of predicates based on the attribute values of the given template instance. For example, this query will find all Employees with a salary of 10000 and rating of 1. The comparison can be further controlled by specifying an optional list of attributes to be excluded from comparison and the style of comparison for String-valued attributes. (SeeResources for a link to the Javadoc for OpenJPA's CriteriaQuery extensions.)
Conclusion This article has introduced the new Criteria API in JPA 2.0 as a mechanism for developing dynamic, typesafe queries in the Java language. A CriteriaQuery is constructed at run time as a tree of strongly typed query expressions whose use the article has illustrated with a series of code examples. This article also establishes the critical role of the new Metamodel API and shows how instantiated metamodel classes enable the compiler to verify the correctness of the queries, thereby avoiding run-time errors caused by syntactically incorrect JPQL queries. Besides enforcing syntactic correctness, JPA 2.0's facilities for programmatic construction of queries can lead to more powerful usage, such as query-by-example, using database functions, and — I hope — many other innovative uses of these powerful new APIs that this article's readers will devise. Acknowledgments I acknowledge Rainer Kwesi Schweigkoffer for his careful review of this article and valuable suggestions, and fellow members of JPA 2.0 Expert Group for explaining the finer points of this powerful API. I also thank Fay Wang for her contribution, and Larry Kestila and Jeremy Bauer for their support during development of the Criteria API for OpenJPA.
���������� �������
������������������������������������� ���
����������� ������������������
�����������������������������
�
����������������������� �!���"��!#�$$���%"�����&���!"$���
� �� ���!�!��"#�$�����% ��� ������� ���� �� �$���
� �&���!�� �������������
� ��������������$����� ���% ��!�������! ����
� ������!��
� '��������� (����������)����*
� +� �����������!����,'-
� '����� $���! $���
� -����$����.���!��������$���������/���
� &0-1��. �2� �������� �3�"0-4
� ����� !���!�������! �
� &����������������!�!������2� �� �
'
(��)��" �*
� �"��5�6� #���!�� !�������$�� ����78����� ���� ���!���
� "���$�� ���9�:�6�������$������ $$��
� 9� !���� (� �� �� �;��� (������ ��������<
� ���-��.��=�� �� ���>?
� @� � !����� � �� ����AA
+
�����,�- './0
� �"��B�6� "���$�� ����C��!���� ���� ���!���
� �!!����� ��������� !���������!���! �����������
� �(��! !�2� ��������
� �!!��@�� ����"#���� � ��;���' ��! ���"#
� &������$���D��!���
� ������ -��.����� $ � �� ����� � ����� �
� #� �� !������������
1
������� �!���"��!#�$$���2�������!�
� ���� �
� 9������ �
� &��������� � ����$�����! �������E
� ��� !!�� ����� �
� �������!!� ��
� F ���������
� ?� 1�1�� ���� 1�1�������1�1�� �����1�1���
� @��� ��������! � !�;���% �����@��� ������& ��-�������'�
� @�����/ !� ��� !<������@��������������� �� ��
� #�� ����
� &���� ��� ��%��� !������������ �� �������3������4
3
������� �!���"��!#�$$���4�5�������
� �� � ������ �����
� @��� �������$����������� � ����$�����! �������E
� @��� �������$� �� !!�� ����� �
� ��� !!�� ����� �
� G � !� �� !!�� �8� �� !!�� ��;���� ���������
� " ���� ������! � !�����
� #���� !�'��������
� '�� �� ����������������������
� +��!�� �������� 1����$�� ����. ���������
� ������� ���������$����� 1�� ���� 1�������1��
/
6"!!����"��"%(����78$��
@Entity
public class Person { @Id protected String ssn; protected String name; protected Date birthDate; . . . @ElementCollection protected Set<String> nickNames;
}
9
6"!!����"��"%(����78$��
@Entity
public class Person { @Id protected String ssn; protected String name; protected Date birthDate; . . . @ElementCollection @CollectionTable(name=”ALIAS”) protected Set<String> nickNames;
}
:
6"!!����"�"%2;��**��!�78$��
@Embeddable public class Address { String street; String city; String state; . . .}
@Entity public class RichPerson extends Person { . . . @ElementCollection protected Set<Address> vacationHomes; . . . }
.�
# !��$!�����!�"%2;��**���
@Embeddable public class ContactInfo {@Embedded Address address;
. . .}
@Entity public class Employee { @Id int empId; String name;
ContactInfo contactInfo; . . . }
..
2;��**��!��5��� �!���"����$�
@Embeddable public class ContactInfo { @Embedded Address address; @OneToMany Set<Phone> phones; . . .}
@Entity public class Employee { @Id int empId; String name;
ContactInfo contactInfo; . . . }
.�
��*���*�����
@Entity public class CreditCard { @Id long cardNumber; @OneToOne Person cardHolder; . . . @OneToMany @OrderColumn List<CardTransaction> transactions;}
.'
#�$�
@Entity public class VideoStore { @Id Integer storeId; Address location; . . . @ElementCollection Map<Movie, Integer> inventory;}
@Entity public class Movie { @Id String title; @String director; . . .}
.+
� �";������$���&�!���"�
���� ��� �����������)�;� !*����)�� �*
@Entity public class Order { @Id int orderId; . . . @OneToMany(cascade=PERSIST, orphanRemoval=true) Set<Item> lineItems; . . .}
.1
<�8�����%����
� ����'�� ������
� +� !����� � ������� ��
� ?� � ������� ��$������ ��� ���� �� ����
� ����'�� �
� +� !������ �� ���� �� ���� (
� ���� ��� !�;�� ��$����!��
� ?� �����<�� ������� �� ��$��!��� $� ������ 0� ���E
� 0� ������� !0� ��
� +� !�$���2� ������$������������ �����!�����2� ���
( �����
.3
��������������= ��8���� ���
� &����1�� !�&0-1��. �2� ��������
� &�-�@����F?'��H=�F����F?+"�9I��?F>�F�9I�E
� 0� �� ��;�� ��� ��� �!�������! �
� ���� ���� ��� ���������
� &�������� ������������!�1�����
� '�� !�����&0-����� ���� �! �
� &������������!�!��������
&�-�@���D��3������ 4
�F?'�?�! �����?#G������!�����
H=�F��������� ��!!� ���/���J�KLM:65N
./
��������������= ��8���� ���4�5�������
� &������$������� ;���! ������!��������$ �� �
� ?� ������!�$������������ � �����
� @� ����� �� �������$� (�� ������
� F ���� !�������������
� @��� ����1 �� !���� ���$���#G1 (�� ������
.9
�=�4�5�$����"��
#G>�,��������������
O�I��D�-+����G�FI����� �
@�&���@?�-�&@���G+--#������ ���������������
�I"������������������������
.:
��*���*�����
&�-�@��
�F?'�@� !�@�!����?#G������������
H=�F������!=��! ���� �J�P�����>� P
�����G>�#G>�,34�Q�56
��
#�$�
���#� ��������'�Q'� � ��#� � �R
&�-�@�� ���������� ��O�I3�4��� ��D�-+�3�4�
�F?'�D�! �&�� � ��?#G� ��� ������
H=�F��O�I3�4�!�� ����-#O��PS=������.SP
�����G>�D�-+�3�4�R�6
�.
6���2>$�����"��
+">���������� �
&��� ������J
����@�&�� �����
��������H=�G�5��=�G� ������T�5�67
��������H=�G�B��=�G� ������T�5�6B
���������-&�� ������T�6�L7
�����G>
��
��������*"!8;"�$���;
&�-�@��
�F?'������� �
H=�F���I"�3 4�#G�< ����� �
�'
6���������4�5�������
� ?�% �1�� !��"#�$�������!����2� �� �
� > ���� !�����������"0-�� �����
� &��������� !
� 9� !������ 1�$ �� ��! ���$�� ���� ������ ���!�
� ���������
� = ���� ��$�� �� � ����
� &���������% �1�� !���������1�� !�� �����
� 0� ���������������! ���� ���� ���������
�+
6���������?6"�������%����
� @�� ��9���! �
� +� !�������������� ���2� �� ���� � ��������� !�� �����! �����
� @�� ��0� ��
� +� !���!!���� ��� �����;� �2� ��� � � ��
� $������ � ���;� � ����! �9��������9���� ����E�� ��!�
� F��
� 0� �������
� ������-��������'�������E
� ������$������������ (������%���
� "�
� G ������$����������%����������
� &��2� ��
�1
�"5�"( �!*�6�������= ��8
������������ �����
������������������� ������������������
������������������� !��"�����
����������������������� ��������
�##����������!�����"����$�# �����������������
%#�����������&������������!�'����'#������
�
�"�����������
�������()����
�������#��������
��������#� ������
�� ������������� !��"��� �����������"�����
*����������� !����������"�������*������
�3
@�!�*���"�4�5�������
� - �� ��;��.��$�9 ��D��!����3�&F�:6:4
� ������� ��!�����������$ ���� � ��
� "� " ����
� "� +�!
� "� F ��
� D��!���1��! � � � �����)� ���� �� �(��*
� �+�?��@�--9�@O��G?G�
� &�!�!�/�����$��������$��������������
�/
-�;$!�&�������
?�! ��
&����� �
"��!��
&����� �
@�!��,
"��!��
9��. >D> @>
@���� � @� !�@�!
"���
�9
#���;"*�!
� ������)��� �1� �*� � ;��$���� !����� �
� ���� ������ !���� ����� ��� �� !!�� �
� ��� �� !�!��������
� ����'�� �������� ' ��! �34
� ����'�� ��� ' ��! �34
� ��!����� ����/ !�������� ��! ������ �
� +� !����� ��������1�� !���� ���2� �� �
� &� ��! $�� ����������$���
�:
javac -processor org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProcessor -sourcepath src -d src -classpath /ace2_apps/eclipselink/jlib/eclipselink.jar:.:/ace2_apps/eclipselink/jlib/JPA/javax.persistence_2.0.0.v200911271158.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
A���������-�����#���;"*�!
'�
2����86!���
��+���# �,� ��
� #���'�-�,� ���������������
� #���'�-�,� ��������.��
� #���'�-�,� ��������� �����
� #���'�-�,� ��������/��#�����
� #���'�-�������0��
1������
����������������# ��2
��1.����������.��
��1� �����3�������������
��1/��#�����0��/���!�#�����
���
4
'.
#���;"*�!6!��� ��+���# �,� ��
� #���'�-�,����#����#��5������
� #���'�-�,� �������� �� #���0�3��������
� #���'�-�,� �������� �� #���0������3��������
� #���'�-�,� �������� �� #���0�������� #���
15������6���� �*��+�%73�8�9����#�������#���5�����#�:�
10�������� #�������# ��������
����������������# �;�2
�� �������������-#������0������3������������# �&.���!�����.��
�� �������������-#������0������3������������# �&3�����!�
�������
�� �������������-#������0�3������������# �&/���!�#�����
���
4
'�
6"�� �����8
� � �" ���� �� ����� ������������������ ���
� &���1 ���� !����.�
� -���1 ���;�� ����.�
� "�� �! �����! $ ��;��������!�� ����������������
� �������������$�������!�� ����! ��!
� ?��������)���.���*�!�� � �� ���������� �
� #� ��������� �������� ������ !������� �! �
� "�� �! �� ��! �� ������;� ��;��������!��
� �(���������.34������ ���� ��� ��! �� !�!
''
����;������"�)���4�5�������
� � �" ���� �� ����� ������������������ ���
� G������ ������������.���
� " ���� ��� ��$� ���
� F ������������� � ������ �����
� ����!�� ����.����$���
� �"���� ��! $�� ��� ����������� ������
� "�� �! ��������.���� �3���� ��4
� -��.���! �
� "�&&#'#&�#@UF��>�V�������� !����.
� "�&&#'#&�#@UHF#���V����� (����� ����.
� "�&&#'#&�#@U�?F@�U#G@F�'�G��V���! � �����
'+
�"�)������
� ����'�� ��� ��!�<����.��$��!��� $� ��
� 0� �������� !0� ���� ��!�<�� -��.'�! ��� =��
� G� !0� ���������<����.'�! � � � �
� % (�� ���� �� ����.����� ����� ��
� % (�� ���� �� ����.��� ������
� " ��������-��.�(� �����3�$�����������������.4
� -��.��� ���(� �����3�$������� � ����������.4
'1
6������6"�%�� ����"�4�5�������
� ����'�� ��� ���� �� ���� (����� ����!����
)$����� �*����
� ���� ����� !����� ���� �� ���� �! �
� ���� ��� !�$����!��
� ���� ����� �;�� ����!��
� '������� � ������������ �� ���!1� ����� �
� G���;�������� ������������
� �"��B�6���!�!�/ �������� ���!1� ����� �
������
'3
-���*��*6"�%�� ����"��"$������
� % (�� ���� �� �%!���!�� �
� % (�� ���� �� �%!������
� % (�� ���� �� �%!����� �
� % (�� ���� �� �%!������;��!
� �����
'/
- ;;��8"%�����4�5���� ���
� '�� �$� (��� ���! ������������ �
� �(��! !�?�F��������$���������
� �!!��������� �" ���� �� �2� ��������
� @�� ����"#
� ' ��! ���"#
� " ������������.���
� &������$��� ��!���
� &�!�!�/�����$��������$��������������
���������� �������
������������������������������������� ���
����������� ������������������
�����������������������������
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
07 private String MimeType; // Useful to store the mime type incase you want to send it 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
11 @Basic(fetch=FetchType.LAZY) // this gets ignored anyway, but it is recommended for blobs
12 protected byte[] imageFile; Using a simple bit of Java code taken from the Java Developers Almanac, we read the file and return it as a byte array. 01 public byte[] readImageOldWay(File file) throws IOException 02 {
03 Logger.getLogger(Main.class.getName()).log(Level.INFO, "[Open File] " + file.getAbsolutePath());
04 InputStream is = new FileInputStream(file); 05 // Get the size of the file 06 long length = file.length(); 07 // You cannot create an array using a long type. 08 // It needs to be an int type. 09 // Before converting to an int type, check 10 // to ensure that file is not larger than Integer.MAX_VALUE. 11 if (length > Integer.MAX_VALUE) 12 { 13 // File is too large 14 } 15 // Create the byte array to hold the data 16 byte[] bytes = new byte[(int) length]; 17 // Read in the bytes 18 int offset = 0; 19 int numRead = 0; 20 while (offset < bytes.length && (numRead = is.read(bytes, offset, bytes.length - offset)) >= 0)
21 { 22 offset += numRead; 23 } 24 // Ensure all the bytes have been read in 25 if (offset < bytes.length) 26 { 27 throw new IOException("Could not completely read file " + file.getName()); 28 } 29 // Close the input stream and return bytes 30 is.close(); 31 return bytes; 32 } We create an entity object and use the entity manager. 01 /* 02 * Put a JPG image into the db 03 */ 04 ImageExample myExample = new ImageExample(); 05 myExample.setMimeType("image/jpg"); 06 file = new File("images/mushroom.jpg"); 07 try 08 { 09 // Lets open an image file 10 myExample.setImageFile(mainCourse.readImageOldWay(file)); 11 } 12 catch (IOException ex) 13 { 14 Logger.getLogger(Main.class.getName()).log(Level.SEVERE, null, ex); 15 } Then we persist the entity object.
1 fatController.create(myExample); This works easily as well for PDF documents view source print? 01 /* 02 * Put a PDF into the db 03 */ 04 ImageExample myExampleTwo = new ImageExample();
05 myExampleTwo.setMimeType("application/pdf");
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);
19 Logger.getLogger(Main.class.getName()).log(Level.INFO, "The number of objects is : " + 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 //26 ou27 try28 { 29 m30 } 31 ca32 { 33 L34 } 35 } 36 else37 { 38 Lo39 } 40 } If you are 01 public02 { 03 Out04 // W05 fo.w06 // f07 fo.fl08 // C09 fo.c10 } Of courseprobablyknow wh
write out thutfile = new Fy
mainCourse.
atch (IOExcep
Logger.getLog
e
ogger.getLogg
e wondering
c void writeF
tputStream fWrite the dawrite(data); flush the filelush(); Close the dolose();
e, if you wery follow somehat you are d
he pdf file File("out/tes
writeFile(ou
ption e)
gger(Main.cl
ger(Main.cla
g what code I
File(File file,
fo = new Fileata
e (down the t
oor to keep th
re to use thise better bestdoing
st"+images.g
utfile, images
lass.getNam
ass.getName
I used to wr
byte[] data)
eOutputStre
toilet)
he smell in.
s in productt practices. I
get(i).getId()+
s.get(i).getIm
me()).log(Level
()).log(Level.S
ite it to a file
throws IOE
eam(file);
tion you wouI have also s
".jpg");
mageFile());
l.SEVERE, n
SEVERE, "U
e, it was sim
Exception
uld add morskipped a lot
null, e);
Unknown file
mple like this
re error chect of steps, as
e type");
s.
cking, and ssuming youu
OptimistOptimistprevent cconflict. Jcheck is databasewith @Ve
public cla @ID in@Version The Versbe an int
“UPDATE WHER
The advascalabilitupdates. OptimistIn the opThe tranwith the e1 versio
tic Concurric locking lecollisions, thJPA Optimismade upon
e since the eersion as sho
ass Employent id; n int version
sion attributet, short, long
E Employee RE id = ? AN
antages of opty. The disad
tic Lockingptimistic locksaction on tupdate. The
on attribute i
JPA
rency ets concurrenhis works bestic locking acommit andntity was reown below:
ee {
n;
e will be incg, or timesta
SET ..., versND version =
ptimistic locdvantages ar
g Example king examplhe left comme transactionis higher tha
2.0 Concu
nt transactiost for applicallows anyond an exceptioad. In JPA
remented wamp. This re
sion = versi= readVersi
king are thare that the u
e below, 2 cmits first caun on the righan when e1
urrency a
ons process cations wherne to read aon is thrownfor Optimist
ith a succesesults in SQ
ion + 1 on”
at no databauser or appli
oncurrent trusing the e1ht throws anwas read, c
and lockin
simultaneore most concand update an if the versitic locking y
ssful commitQL like the fo
ase locks areication must
ransactions 1 version attrn OptimisticLausing the t
ng
usly, but decurrent tranan entity, hoion was updou annotate
t. The Versioollowing:
e held whicht refresh and
are updatinribute to be LockExceptitransaction
etects and nsactions do owever a versated in the
e an attribut
on attribute
h can give bed retry failed
ng employee incremente
ion because to roll back.
not sion
te
can
etter d
e1. d the
.
Additional Locking with JPA Entity Locking APIs With JPA it is possible to lock an entity, this allows you to control when, where and which kind of locking to use. JPA 1.0 only supported Optimistic read or Optimistic write locking. JPA 2.0 supports Optimistic and Pessimistic locking, this is layered on top of @Version checking described above. JPA 2.0 LockMode values :
� OPTIMISTIC (JPA 1.0 READ): o perform a version check on locked Entity before commit, throw an
OptimisticLockException if Entity version mismatch. � OPTIMISTIC_FORCE_INCREMENT (JPA 1.0 WRITE)
o perform a version check on locked Entity before commit, throw an OptimisticLockException if Entity version mismatch, force an increment to the version at the end of the transaction, even if the entity is not modified.
� PESSIMISTIC: o lock the database row when reading
� PESSIMISTIC_FORCE_INCREMENT o lock the database row when reading, force an increment to the version at the
end of the transaction, even if the entity is not modified.
There are multiple APIs to specify locking an Entity: � EntityManager methods: lock, find, refresh � Query methods: setLockMode � NamedQuery annotation: lockMode element
OPTIMISTIC (READ) LockMode Example In the optimistic locking example below, transaction1 on the left updates the department name for dep , which causes dep's version attribute to be incremented. Transaction2 on the right gives an employee a raise if he's in the "Eng" department. Version checking on the employee attribute would not throw an exception in this example since it was the dep Version attribute that was updated in transaction1. In this example the employee change should not commit if the department was changed after reading, so an OPTIMISTIC lock is used : em.lock(dep, OPTIMISTIC). This will cause a version check on the dep Entity before committing transaction2 which will throw an OptimisticLockException because the dep version attribute is higher than when dep was read, causing the transaction to roll back.
OPTIMISIn the OPwants to locks theem.flushcause antransactibe stale,
STIC_FORCEPTIMISTIC_Fbe sure tha
e dep Entity h() which cauny parallel upion1 on the an Optimist
E_INCREMEFORCE_INCat the dep na
em.lock(deuses dep's vepdates to deleft at commticLockExcep
ENT (write) REMENT locame does noep, OPTIMISersion attribep to throw mit time wheption is thro
LockMode cking examp
ot change duSTIC_FORCEbute to be in
an Optimistn the dep ve
own
Example ple below, truring the traE_INCREMEcremented iticLockExceersion attrib
ransaction2ansaction, soENT) and thin the databeption and robute is check
on the righo transactionhen calls ase. This wioll back. In ked and foun
t n2
ill
nd to
Pessimis
Pessimis(SELECTupdate thconcurrePessimistransactiThe exam
1. re2. re3. re
The Traddeadlockoptimisti
The right
� w� W� W
stic Concur
tic concurreT . . . FOR UPhe same entent access totic locking isions. mples below eading an eneading an eneading an en
de-offs are thks. The later ic lock excep
t locking app
what is the riWhat are the What are the
rrency
ency locks thPDATE [NOWtity at the sao the data whs better for a
show: ntity and thentity with a lntity, then la
he longer youyou lock the
ption, if the e
proach depe
isk of risk ofrequiremenrequiremen
he database WAIT]) . Pesame time, whhich can cauapplications
en locking itlock ater refreshin
u hold the loe greater theentity was u
ends on your
f contention nts for scalabnts for user r
row when dssimistic lockhich can simuse bad scals with a high
t later
ng it with a
ock the greae risk of stal
updated after
r application
among concbility? re-trying on
data is read, king ensure
mplify appliclability and
her risk of co
lock
ater the risksle data, whicr reading bu
n:
current tran
failure?
this is the ees that transcation code, may cause d
ontention am
s of bad scalch can then ut before lock
nsactions?
equivalent ofsactions do nbut it limitsdeadlocks. mong concur
lability and cause an
king.
f a not
rrent
JPA PerfDatabaseGood Daoptimizatdisk read
Data TypYou shoudata typewill be.
NormalizDatabasethere is lmakes qufor applicapplicatioften needuplicateyou can uwhose @identity o
formance, De Schema
atabase schetions is to dds faster and
pes uld use the ses, the more
zation e Normalizatless data to cueries slowecations invoons. You shed to mix thee, or cache, use the @EmEmbeddableof the entity
JPA PerDon't Ignore
ma design isesign your td uses less m
smallest date indexes (an
tion eliminatchange. How
er, denormallving many thould normae approacheselected columbedded ane type can be.
rformance, e the Datab
s important tables to takmemory for q
ta types possnd data) can
tes redundawever a Normlization speetransactionsalize your sces, for exampumns from onotation for e stored as a
Don't Ignorbase
for performe as little spquery proces
sible, especifit into a blo
ant data, whimalized scheeds retrieval.s, less normchema first, tple use a parone table in denormaliz
an intrinsic
re the Datab
ance. One opace on the dssing.
ially for indeock of memo
ich usually ema causes . More norm
malized are bethen de-norrtially normanother tabed columns part of the o
base
of the most bdisk as poss
exed fields. Tory, the fast
makes updajoins for que
malized schemetter for rep
rmalize latermalized schemble. With JPA
to specify aowning entit
basic sible , this m
The smaller yter your quer
ates faster sieries, whichmas are bettorting types. Applicatioma, and A O/R mappa persistent fty and share
makes
your ries
ince h ter s of ons
ping field e the
DatabaseThe Clas
In the Sinsingle tabby @Discqueryingin every rcolumns
In the Joa single tthat subcupdates.hierachie
e Normalizas Inheritanc
ngle table peble in the dacriminatorCg, no joins arrow, a deep .
oined Subclatable, and eaclass. This i However ques, polymorp
ation and Mce hierarchy
er class mapatabase. ThiColumn), whre required. inheritance
ass mappingach subclasss normalized
ueries causephic queries
Mapping Inhshown belo
pping showns table has a
hich identifieDisadvantaghierarchy w
g shown belos has a sepad (eliminates joins whichand relation
heritance Hiow will be us
n below, all ca discriminaes the subclages: wastag
will result in
ow, the root arate table ths redundant
h makes quenships.
iearchies sed as an exa
classes in thator column ass. Advant
ge of space swide tables
of the class hat only cont data) whicheries slower e
ample of JPA
he hierarchy (mapped
tages: This iince all inhe with many,
hierarchy isntains those h is better foespecially fo
A O/R mapp
are mapped
is fast for erited fields , some empt
s representefields speci
or storage anor deep
ping.
d to a
are ty
d by fic to nd
In the Tamapped not normsame typ
Know whYou needperformacheck thcan enab
<properti <prope</proper With Hib
<properti <prope</proper
able per Clasto a table in
mlalized, inhepe are fast, h
hat SQL is ed to understance. Its a goe executed S
ble logging o
ies> erty name="rties>
bernate you s
ies> erty name="rties>
ss mapping n the databaserited data ihowever poly
executed and the SQLood idea to eSQL. Logginf SQL by set
eclipselink.l
set the follow
hibernate.sh
(in JPA 2.0, se and all this repeated wymorphic qu
L queries youenable SQL lng is not partting the foll
logging.level
wing propert
how_sql" val
optional in he inherited which wasteueries cause
ur applicatiologging, thenrt of the JPAowing prope
" value="FIN
ty in the per
lue="true" />
JPA 1.0), evstate is repe
es space. Que unions whi
on makes ann go through
A specificatioerty in the pe
NE"/>
rsistence.xm
>
very concreeated in thaueries for Enich are slow
nd evaluate h a use caseon, With Ecliersistence.x
ml file:
ete class is at table. Thisntities of the
wer.
their e scenario toipseLink you
xml file:
s is e
o u
Basicallydata thananalyzing
� qu� re� qu
With MyScan use tEXPLAIN
UnderstaFor slow informatiSELECT,find miss
You shoucolumns updates.
Lazy LoaWith JPAbe loadedyou needis the nu
y you want ton it needs, ag more rowsueries whichetrieving moueries which
o you ca
SQL you canthe MySQL q
N statements
anding EXPqueries, youion about th, including sing indexes
uld index cofrequently u
ading and JA many-to-ond when the ed to access aumber of "ma
o make yourare queries as than it neeh execute toore data thanh are too sloan use EXPL
n use the sloquery analyzs.
PLAIN u can precedhe query exeinformation
s early in the
lumns that used in joins
JPA ne and manentity in theall of the "maany" objects
r queries accaccessing toods? Watch oo often to ren needed ow LAIN to see w
ow query logzer to see slo
de a SELECTcution plan,about how
e developmen
are frequents, but be aw
ny-to-many re relationshipany" objects .
cess less dato many rowsout for the foetrieve neede
where you s
g to see whicow queries,
T statement , which expltables are jont process.
tly used in Qware that ind
relationshipsp is accessedin a relation
ta, is your as or columnollowing: ed data
should add in
ch queries arquery execu
with the kelains how it oined and in
Query WHERdexes can slo
s lazy load bd. Lazy loadnship, it will
application rs? Is the dat
ndexes
re executingution counts
eyword EXPLwould proce
n which orde
RE, GROUP ow down ins
by default, mding is usuall cause n+1
retrieving motabase query
g slowly, or ys, and result
LAIN to get ess the er. This help
BY clauses,serts and
meaning theylly good, butselects whe
ore y
you ts of
s
and
y will t if re n
You can
However fetch too related c If you waexample
In Generlog, and
change the
you should much data.
ollections.
ant to overridthis query w
ral you shouuse @NameQ
relationship
be careful w. It can caus
de the LAZYwould eagerl
ld lazily loadQueries with
p to be loade
with eager lose a Cartesia
Y fetch type fly load the e
d relationshih JOIN FETC
d eagerly as
oading whichan product i
for specific umployee add
ips, test youCH to eagerl
s follows :
h could causf you eagerly
use cases, yodresses:
ur use case sly load when
se SELECT sy load entiti
ou can use F
scenarios, chn needed.
statements ties with seve
Fetch Join. F
heck the SQ
that eral
For
QL
Partitionthe mainso that th Vertical columnsincluding Horizontdatasets example partition
Vertical In the exBLOB cocolumns By removmore freqalways en
ning n goal of parthe overall re
Partitionin, so that onlg all rows.
tal Partitionare formed.of horizontaed by date.
Partitionin
xample of verolumns that
in one table
ving the largquently accensure that a
titioning is tesponse time
ng splits tably certain co
ning segmen All columns
al partitionin
ng
rtical partitioaren't referee and the se
ge data columessed Customall columns d
to reduce thee is reduced
bles with malumns are in
nts table rows defined to ng might be
oning belowenced often ildom-referen
mns from thmer data. Wdefined to a
e amount of
any columnsncluded in a
ws so that dia table are fa table that
w a table thatis split into nced text or
he table, youWide tables ca
table are ac
f data read fo
s into multipa particular
istinct groupfound in eaccontains hi
t contains a two tables wBLOB colum
u get a fasteran slow dowctually neede
for particular
ple tables witdataset, wit
ps of physicach set of paristorical data
a number of vwith the mosmns in anot
r query respwn queries, sed.
r SQL opera
th fewer th each parti
al row-basedrtitions. An a being
very wide test referencedther.
onse time foso you shoul
ations
ition
d
ext or d
or the ld
The examthe moreCustomeCustome
mple below se frequently erInfo table werInfo Entity
shows the JPaccessed anwith the lesswith a lazily
PA mapping nd smaller das frequently y loaded one
for the tableata types isaccessed ane to one rela
es above. Ths mapped to nd larger datationship to t
he Customerthe Custom
ta types is mthe Custome
r data table
mer Entity, thmapped to ther.
with he he
HorizontThe majo Horizontapartitionnecessardatabasedatabase
HibernatPartitionextreme primary a Hibernatpartition
tal Partitionor forms of h
al partitionins contain th
ry partitions e Applicatione tables.
te Shards ing data horscalability foaccess path
te Shards is ing into the
ning horizontal pa
ng can makehe data that
during querns that conta
rizontally intor very large.
a frameworkHibernate C
artitioning a
e queries faswill satisfy ary executionain a lot of q
to "Shards" e amounts of
k that is desCore.
are by Range
ster becausea particular n. Horizontalquery activity
is used by gf data. eBay
signed to enc
e, Hash, Has
e the query oquery and wl Partitioningy that target
google, linkedy "shards" da
capsulate su
sh Key, List,
optimizer knwill access og works bests specific ra
din, and othata horizonta
upport for h
and Compo
nows what only those t for large anges of
hers to give ally along its
orizontal
osite.
s
Caching JPA Levereading ffrequent You shou
� re� m� N
You shourefresh...
JPA Leve
JPA has
The JPA
el 2 caching frequently acor concurre
uld configureead often
modified infreNot critical if uld also conf.
el 1 caching
2 levels of c
Entity Mana
avoids databccessed unmently update
e L2 caching
equently f stale figure L2 (ve
g
aching. The
ager maintai
base access modified entid entities.
g for entities
endor specifi
JP
first level of
ins a set of M
for already ities faster, h
s that are:
ic) caching f
PA Caching
f caching is
Managed En
loaded entithowever it c
for maxElem
the persiste
ntities in the
ties, this macan give bad
ments, time t
ence context
e Persistence
ake reading scalability f
to expire,
.
e Context.
for
The Entitdatabasemanagedlocking a
The codethe same
@Stateles @Persist public O Ord enti OrdorderLin (orde retu } }
ty Manager e row, there d in another as explained
e below showe persistence
ss public Sh
tenceContex
OrderLine crederLine ordeityManager.p
derLine ordene.getId())); erLine == orurn (orderLin
guarantees will be only User's trans
d in JPA 2.0
ws that a finde context , w
hoppingCartB
xt EntityMan
eateOrderLinrLine = new persist(orde
erLine2 =ent
rderLine2) ne);
that within one object isaction, so yConcurrenc
d on a manawill return th
Bean implem
nager entityM
ne(Product pOrderLine(o
erLine); //MtityManager
// TRUE
a single Persnstance. Hoyou should ucy and lockin
aged entity whe same inst
ments Shopp
Manager;
product,Ordorder, produManaged .find(OrderL
sistence Conowever the sause either opng
with the samtance.
pingCart {
der order) { uct);
Line,
ntext, for aname entity cptimistic or
me id and cla
ny particularcould be pessimistic
ass as anoth
r
her in
The diagr
The codeEntityMacreated abecause when thiorderline
The Persthe lengttransactiend of a
ram below s
e below illustanager is injand the entitit is a statelis transactioe entity is ret
istence Conth of the tranions. With a transaction.
shows the lif
trates the lifected using ty has the stless session on commits ,turned at th
text can be ensaction, or Transaction
.
fe cycle of an
fe cycle of anthe persistetate of new. bean it is by, the order is
he end of the
either TransExtended--
n scoped Per
n Entity in re
n Entity. A rence contextPersist is cay default usis made perse transaction
saction Scopthe Persiste
rsistence Co
elation to th
reference to t annotationalled, makining containeistent in the
n it is a deta
ped-- the Perence Contextontext, Entit
he Persistent
a container . A new orde
ng this a maner managed e database. Wached entity.
rsistence Cot spans mulies are "Deta
t Context.
managed er entity is naged entitytransactionsWhen the .
ontext 'lives' ltiple ached" at th
y. s ,
for
he
As shownmerge() opersisted
An ExtenPersisten"conversa
n below, to poperation, wd to the data
nded Persistence Context ation" with a
persist the chich returns
abase at the
ence Contexstay Managea user spans
changes on as an updatedend of the tr
xt spans mued. This cans multiple re
a detached ed managed eransaction.
ltiple transan be useful inequests.
entity, you caentity, the e
actions, and n a work flow
all the Entitntity update
the set of Ew scenario w
tyManager's es will be
Entities in thwhere a
he
The codeContext icreateOraddLineIwill be pe
The examContext vcontext, Entity whThe perfoweighed entities bcontentioscalabilit
e below showin a use casder method,tem methodersisted at th
mple below cverses an exan Entity Mhich can be ormance advagainst the
being updateon among coty.
ws an exampe scenario to, it remains
d , the Orderhe end of th
contrasts upxtended Persanager find updated. W
vantage of ndisadvantaged by anotheoncurrent tra
ple of a Stateo add line Itmanaged un
r Entity can he transactio
pdating the Osistence contmust be donith the Exte
not doing a dges of memoer transactioansactions t
eful Session tems to an Ontil the EJB be updated
on.
Order using text. With thne to look unded Persist
database reary consumpon. Dependithis may or
EJB with anOrder. After t
remove metbecause it i
a transactiohe transactio
up the Ordertence Conte
ad to look upption for caching on the amay not giv
n Extended the Order isthod is calleis managed,
on scoped Peon scoped p, this return
ext the find ip the Entity, hing, and th
application ae better perf
Persistence persisted ind. In the and the upd
ersistence ersistence
ns a Manageis not necessmust be
he risk of cacand the risk formance /
n the
dates
ed sary.
ched of
JPA seco
JPA seco
JPA 1.0 dprovidersoperationbelow:
ond level (L
ond level (L2
did not specs provided suns with the n
L2) caching
) caching sh
cify support upport for snew Cache A
hares entity s
of a second econd level cAPI, which is
state across
level cache, cache(s). JPs accessible
s various per
however, mPA 2.0 specif
from the En
rsistence con
most of the pfies support ntityManage
ntexts.
ersistence for basic ca
erFactory, shache hown
If L2 cachif found.
The adva� av� fa
The disad
� m� S� C� B
You shou
� re� m� N
You shou
� M� co
The Quermodified
hing is enab
antages of L2voids databaaster for read
dvantages omemory cons
tale data forConcurrency Bad scalabilit
uld configureead often
modified infreNot critical if
uld protect aMust handle onfigure exp
ry cache is utables.
bled, entities
2 caching arase access foding frequen
f L2 cachingsumption forr updated obfor write (opty for freque
e L2 caching
equently f stale
any data thaoptimistic lo
piration, refr
useful for qu
s not found i
re: or already lontly accessed
g are: r large amoubjects ptimistic locent or concu
g for entities
at can be conock failures resh policy to
ueries that a
in persistenc
oaded entitied unmodifie
unt of object
k exception,rrently upda
s that are:
ncurrently mon flush/coo minimize l
are run frequ
ce context, w
es ed entities
ts
, or pessimisated entities
modified withommit lock failures
uently with t
will be loade
stic lock) s
h a locking s
s
the same pa
ed from L2 ca
strategy:
rameters, fo
ache,
or not
The Ecli
The Ecli
Support cached. Yentity id following
� C� C� M� M
The exam
ipseLink JP
ipseLink cac
for second lYou can disaand state in
g configurati
Cache isolatioCoordinationMessaging: JMode: SYNC,
mple below s
PA persisten
ching Archite
evel cache inable the L2 cn L2. You caon paramete
on, type, siz(cluster-me
MS, RMI, RMSYNC+NEW
shows config
nce provider
ecture is sho
n EclipseLincache. Eclipn configure ers:
ze, expirationessaging) MI-IIOP, …
W, INVALIDA
guring the L2
r caching A
own below.
nk is turned seLink cachcaching by E
n, coordinati
ATE, NONE
2 cache for a
Architecture
on by defauhes entities iEntity type o
ion, invalida
an entity us
e
ult, entities rin L2, Hibernor Persisten
ation,refresh
ing the @Ca
read are L2 nate caches
nce Unit with
hing
ache annotat
h the
tion
The Hibe
The Hibenot confidifferent into Hibe
The confishows co
ernate JPA
ernate JPA pigured by deL2 caches. T
ernate.
figuration of onfiguring th
persistence
persistence pefault, it doesThe diagram
the cache dhe hibernate
e provider c
provider cachs not cache
m below show
depends on te L2 cache fo
caching Arc
hing architeenities just ws the differ
the type of caor an entity u
chitecture
ecture is diffeid and state
rent L2 cach
aching plugusing the @
ferent than Ee, and you cahe types that
ged in. The Cache anno
EclipseLink: an plug in t you can plu
example bel
otation
it is
ug
low
Best Practices: Testing JPA
Greetings all. I have set up a structure for creating some JPA entities. I am using spring, hibernate entity manager, maven and derby to create a 'test environment' and everything seems to work. I can create an 'AbstractJpaTests' subclass and run unit tests with the entity manager to my heart's content. What I am wrestling with, is the best practices for doing these kind of tests. It seems that writing tests of CRUD operations against every JPA entity that I create is a very tedious approach. I have also considered creating an abstract subclass of AbstractJpaTests which templates the basic CRUD tests and uses abstract methods as factories, so that new JPA tests can be created by creating concrete subclasses and implementing these basic abstract methods. This starts to get a little problematic when dealing with relationships and complex object graphs though. I have also had it suggested to me that there is no need to write unit tests of CRUD operations on JPA entities as any problems will be found when doing the higher level tests of business methods and that testing against an embedded derby instance will not always mean the entities will work in other RDMS setups. I am curious about how others approach this subject. Is everyone writing CRUD tests for each of thier entities? Do you have some better approach? Are you testing them at this level at all?
JPA implementation patterns: Testing
What to test?
The first question to ask is: what code do we want to test? Two kinds of objects are involved when we talk about JPA: domain objects and data access objects (DAO's). In theory your domain objects are not tied to JPA (they're POJO's, right?), so you can test their functionality without a JPA provider. Nothing interesting to discuss about that here. But in practice your domain objects will at least be annotated with JPA annotations and might also include some code to manage bidirectional associations (lazily), primary keys, or serialized objects. Now things are becoming more interesting... (Even though such JPA specific code violates the POJO-ness of the domain objects, it needs to be there to make the domain objects always function the same way. Whether inside or outside of a JPA container. The managing of bidirectional associations and using UUIDs as primary keys are nice examples of this. In any case, this is code you most certainly need to test.)
Of course, we'd also need to test the DAO's, right? An interesting question pops up here: why do we want to test the DAO's? Most of them just delegate to the JPA provider and testing the JPA provider makes no sense unless we are writing "learning tests" (see also Robert Martin's Clean Code) or developing our own JPA provider. But the combination of the DAO's and the JPA specific part of the domain objects is testworthy.
What to
Now thatdatabaseembeddesuch as Mset up; thinstancedatabasemore on
For mostand afterschema ado (a.k.aafter the
� TthSthJthu
� Ifthtembute
� Ifexextate
test agains
t we know we code, we wed in-memorMySQL or Ohere is no ne. But if youre issues thisthat later.
t tests we ner the test weand filling th. left as an etest is a mo
he Spring Frhe state of ypringJUnit4hat transactUnit 3.8 youhe same effe
unsatisfactor1. By de
querynot acmappbeforeanym
2. Also, suncovdatabsaved
3. Finallrun thdatabfirst tw
f you use anhe first test aests are run
multiple tranetween each
use the @Dirtests. f you cannotxpensive, yoxample, DbUables. Foreigemporarily d
st?
what to test, want our testry database
Oracle. Usingeed for everyr production way. So an
eed more thae need leave he database exercise for tore difficult p
ramework inour test fixtu
4ClassRunnetion at the enu can extendect. This migry for a numfault the JPA
y is executedctually propaings and sue the end of ore. saving an enver those nasase as the J! y, in a test yhe tests, andase. To test wo transactiembedded i
and you won. This mean
nsactions with test. For extiesContext
t use an in-mou can try anUnit can be gn key contrdisable refere
we can decit fixture to insuch as HSQg an embeddyone runnin
n code runs aintegration
an just the dit in a usablwith the rig
the reader problem. I've
ncludes the ure. If you aer will start nd of the tesd the Abstraght seem nic
mber of reasoA context is
d. So unless agated to thch. You couthe test, but
ntity and thesty lazy load
JPA provider
you might likd finally checthis properlions being roin-memory dn't need to ws you will nothin one testxample, wheannotation t
memory datand clear all tused to dele
raints may gential integr
de what to tnclude a datQLDB (in meded databaseng the tests tagainst anottest against
database. Wele state for t
ght data befo), but retur
e found a nu
a test frameannotate youa transactio
st to return tctTransactio
ce but in prans: not flushedyour test ince database w
uld try and ext then the te
en retrievingding issues. r will return
ke to first stck that the rly you need olled back. database thaworry about ot have to rot. But you men using theto reinitializ
abase or re-ithe tables afete all data fret in the way
rity before pe
test against.tabase. Thatemory-only me has the bigto have a runther databast a real datab
e need to sethe next testore running rning the daumber of app
ework that uur test to be on before eacto a known sonalSpringCactice I've fou
d until the trcludes a quewhich can hxplicitly invoests don't re
g it in the saYou're proba reference
tore some daright data wthree separa
at database leaving it in
oll back any might have toe Spring Testze the in-mem
initializing itfter every tesfrom your teay though, soerforming th
Since we art database cmode) or a "g advantagenning MySQse, you mighbase is also
t it up corret to run. Setthe test are
atabase to a proaches to
uses transac@Transactio
ch test startstate. If you
ContextTestsund this me
ransaction isery, any mod
hide problemoke EntityMpresent real
ame session ably not eveto the objec
ata in the dawas written oate transact
will be cleann a good stat
transactiono do somethtContext framory databa
t after every st (or before st tables or o you will wahese operatio
re testing an be an "real" databa of being eas
QL or Oracle ht not catch
needed, but
ectly before ating up the not that hausable statethis problem
tions to manonal, the ts and roll bau are still usis base class thod to be
s committeddifications a
ms with invalManager.flushl scenario's
does not en hitting thct that you ju
atabase, thenout to the tions withou
n when you te after all thns and can hhing special amework youase between
y test is too every test). truncate allant to ons.
ase sy to
all t
a test
rd to e m:
nage
ack ing for
or a are lid h
e ust
n
t the
run he have
u can
For test
At what scope to test?
The next thing is to decide on the scope of the tests. Will you write small unit tests, larger component tests, or full-scale integration tests? Because of the way JPA works (the leakiness of its abstraction if you will), some problems might only surface in a larger context. While testing the persist method on DAO in isolation is useful if you want to know whether the basics are correct, you will need to test in a larger scope to shake out those lazy loading or transaction handling bugs. To really test your system you will need to combine small unit tests with larger component tests where you wire your service facades with the DAOs under test. You can use an in-memory databases for both tests. And to complete your test coverage you will need an integration test with the database to be used in production using a tool such a Fitnesse. Because we are not specifically testing the JPA code in that case, having unit tests on a smaller scale will help you pinpoint DAO bugs more quickly.
What to assert?
One final thing to tackle is what to assert in the tests. It might be that your domain objects are mapped to an existing schema in which case you want to make sure that the mapping is correct. In this case you would like to use raw JDBC access to the underlying database to assert that the right modifications were made to the right tables. But if the schema is automatically generated from the JPA mapping you probably will not care about the actual schema. You'll want to assert that persisted objects can be correctly retrieved in a new session. Direct access to the underlying schema with JDBC is not necessary and would only make such test code brittle.
I'm pretty sure that I have not covered all test scenarios in this blog because testing database code is a very complicated area. I would love to hear how you test your database code, whether it uses JPA or some other persistency mechanism.
JPA Best Practices
Accessing a database is THE most common task in any IT application. Using one single layer which is more readable, manageable, and maintainable for all apps becomes a real need. JPAis the right step towards that. We can also see that other technologies are emerging and taking advantage of the ease of embedding annotations in entities. Be aware not to make your entities too “heavy”. Too heavy means, less manageable and difficult to reused.
Writing entities with JPA is easy but, if not implemented with love and care it is also might be a real time bomb in terms of performance, once data amounts grow in the persistence layer (e.g tables in the db are getting really big). Here are some JPA best practices and issues that one should take in mind from the very beginning of creating entites: First, you can enable logging of actual SQL being generated by the JPA implementation. Check your environment configuration in order to do that. There are always surprises and this is a good place to start understanding what is going on.
1. Try to avoid joins on tables:
� Merge tables (look for one to one relations). � Divide tables in order to lazy fetching potentially large fields (Blob data for example, lots of
text). � Use Inheritance strategy with single table and @DiscriminatorColumn. � Prefer Lazy fetch type when possible.
2. Use prepared statements in your JPQL (e.g select e from Entity e where e.id = :someId). This will enable compiled statement caching.
3. Don’t start a transaction for read operations.
4. Use Named Queries when possible. Named queries can be annotated with query hints.
5. Understand Caching in order to reduce DB round trips:
� 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.
� There is another provider specific caching feature - read only entities caching , once marked they will be loaded to the persistence unit and will stay there. 4. Don’t order if not needed.
5. Create indexes in tables.
6. Use bulk JPQL statements instead of iterating single operations.
7. Know JPA defaults. This will help you in maintain you entities which might grow to great number.
� For example, the default fetch type for many to one relation is EAGER. Is it always needed/not performance issue? 8. Use cascade property carefully or unnecessary SQL operation will be executed.
9. Validate your connection pool configuration against you application requirements.
10. Consider enabling optimistic locking on an entity.
Conclusion Performance issues are a common ongoing task and most of the times a pretty difficult to track. mostly due to time limitations leading to fast development and no time to redesign. You find your self grab what you can in this area or sit until white smoke comes out of a real performance issue pops up. I hope knowing or just be aware of the above issues will help you in implementing a stable, maintainable and performance aware domain model.
Hibernate/JPA best practices Override hashCode() and equals() The Hibernate reference states that "It is recommended that you implement equals() and hashCode() to compare the natural key properties of the entity." The reason is simple: different instances of the class may represent the same record in the database. Therefore, when comparing these two instances, you'd like to get equal result, while default equals implementation will return not-equal since it's not the same instance. This becomes really important, when working with collections, especially with Sets. You don't want the same object to appear twice in set, right? Overriding the hashCode() and equals() is not a very complex goal, but you must be very careful: 1. Remember that two equal objects must return the same hash code. Therefore, you cannot use auto-generated Hibernate id in hashCode() - this value is not assigned for the newly created objects. After persistence occurs, the value is assigned, so the hashCode will change, when the object actually wasn't changed! 2. Changing the fields that participate in hashCode() will change the hash code value. So if your object is stored in a Set (or it's key of a Map), you won't be able to retrieve it from the set anymore - one hash was used for insert and another one was used for retrieve. So basically you'll need to remember not to change objects that are stored in sets! And this is really important! So you may ask: how will I know who stored my object in a set? My answer is simple: you cannot know this, unless you don't give your objects out. So you are the only person who is using these objects, so you know how they are kept, right? Storing the objects without giving them out is not so weird idea: keep the persistence layer away from the business logic and return a copy of object when required. Another option: return immutable objects to the business tier. So the business tier won't be able to change them. When the change is required - provide a special API. Thus the objects won't change accidentally. Try to Make All Object Immutable This may sound weird, how exactly the persistent objects can be immutable. But in the previous part I described why it's important. And actually it can be quite easily achieved: 1. Make all setters private. Thus it will be impossible to call them without using reflection. (Hibernate will use reflection and populate the properties during the object retrieval) 2. When returning collections, wrap them with Collections.unmodifiable. So the user won't be able to modify your collections. 3. Allow changes only via special methods. Return Copy of Persistent Objects to the Business Tier So no accidental change in hash code may occur. Additionally when filling the business objects, a lot of potential problems may be resolved. Consider that the persistent object contains a lazy collection. If the object is returned as is to the business tier, the lazy elements in the collections can be accessed after the transaction was closed, therefore the query to the database will fail and user will get an exception. h3. Change Data in Collections Only via Special Methods When having associations, take care of this association via special method: for example, Parent class will have method addChild(Child child). When returning the values of collections wrap them using Collections.unmodifiable to prevent accidental changes. This is useful both to handle bidirectional associations correctly and to prevent accidental changes in hash code.
Summary 1. Override hashCode() and equals() of the entities using the natural key properties of the entity. 2. Don't compare auto-generated id in hashCode(). 3. Don't change the properties that participate in the hashCode() for objects stored in collections that use hash code (especially Sets or Maps). If such a change must occur, reinsert object into collection. Remember that remove must occur before the property is updated. 4. Keep the persistence tier away from the business logic as much as possible. Don't pass the persistence objects to the business at all. 5. Make your objects immutable (or semi-immutable): make all setters private, return collection values only wrapped with Collections.unmodifiable, make changes in collections only via special methods.
JPA/Hibernate best practices? Hi, I'm new to ORM. I spent a couple days trying to figure it out and I've got some basic stuff working (JPA, annotations, selecting and persisting using native query and jpa query language). Now i want to start designing an approach for my application, so I have some questions related to best practices for JPA. 1. All of my data access is done through DAO objects. I have a baseDAO superclass where in that constructor I create an instance of a protected EntityManager member object and that manager doesn't ever get .close()'d until the finalize() method of my BaseDAO. Is that ok? Or would it be better to have each method of the DAO call the factory to create/close() a new EntityManager just for the life of the method? 2. Is there a way to detach an Entity from being auto-updated in the database without calling the persist() method? I have a feeling this relates to my manager not being .close()'d until the DAO gets garbage collected...I'd like to be able to change some of my Entity objects database values for display without having the change saved in the db. 3. Let's say I have an Entity with 10 members. I want to do a quick lookup and i'm only going to use 2 of those members for display. What's the best way to tell jpa/hibernate to select and build that entity object with only the data I care about? Hopefully my questions make sense. if you guys have any links to common JPA practices, that'd be great too. Thanks, Aaron
�
�
�
�
�
�
�
�
Enterprise JPA & Spring 3.0 - Tips and Tricks for JEE Persistence
As with many technologies, the basics are easy. The hard part comes when the developer needs to do sophisticated integration, development, and testing as part of an enterprise application. A large enterprise application requires the developer to think of issues that affect the development, scalability and robustness of the application. This presentation will cover the advanced topics described below with a focus on the new persistence features in Spring 3.0 and JPA 2.0.
A large enterprise application often will have several sub-projects that each contain their own JPA persistence unit. This opens up a number of questions around how to organize the persistence units and how the code between sub-projects should interoperate. Developers will gain insight into these issues and will see a couple of solutions using live code examples.
Many enterprise applications require integration with an application server's JTA mechanism. JTA integration allows for JPA components to work with container managed transactions and distributed transactions. A typical usage scenario for JPA & JTA is this: read from a database using JPA, perform some business logic, put a message on a queue, write to the database (again using JPA). A JTA transaction allows you to ensure that the entire set of operations is committed or a rollback is performed. In this presentation, the developer will understand the limitations and configuration of using JTA and JPA together ? primarily through real code examples.
Once unit tests are written, developers often gloss over doing fine-grained integration testing just for their persistence layer. Integration testing with JPA means simply one thing: running your JPA components against your target database, for example, Oracle. Overlooking this aspect leads to problems being discovered later in the test cycle (UAT for example) and makes it more difficult to find and fix bugs. This presentation will use live code examples to explain a strategy for getting integration testing for free by reusing unit tests.
Using optimistic locking versus pessimistic locking seems clear cut to most developers. However, a full understanding of the issues with using pessimistic, or datastore, locking is required before making this decision. Developers will get information in the trade offs when using strategy or the other, and how these strategies can be used together with the same persistence unit.
�
�
�
�
�
�
�
�
�
�
JPA in Java SE December 22nd, 2009 Using JPA on top of the persistence layer makes things much more manageable and maintainable. In EE apps this fact makes a real difference.
Implementing a domain model via objects is another step towards modeling the business. Now days, you will find that more services are available at the entities level. Entities fields can be marked with validation rules (J2EE 6 Beans validation) . Also indexing on top of Lucene is made easy with Hibernate Search (JBoss project).
All these services should be free from any container restrictions and so they are.
I will show a very basic implementation of JPA in Java SE using eclipseLink implementation.
Folder structure -org.jpa.test --Test.class --User.class -META-INF --MANIFEST.MF --persistence.xml Entity Mapped to a table in the DB. import java.io.Serializable; import javax.persistence.Column; import javax.persistence.Entity; import javax.persistence.GeneratedValue; import javax.persistence.GenerationType; import javax.persistence.Id; import javax.persistence.Table; /** * The persistent class for the users database table. * */ @Entity @Table(name = "users") public class User implements Serializable { private static final long serialVersionUID = 1L; @Id @GeneratedValue(strategy = GenerationType.AUTO) private String id; @Column(name = "Name") private String name; @Column(name = "Zip") private String zip; @Column(name = "Address") private String address; public User() { }
public String getId() { return this.id; } public void setId(String id) { this.id = id; } public String getName() { return this.name; } public void setName(String name) { this.name = name; } public String getZip() { return this.zip; } public void setZip(String zip) { this.zip = zip; } public String getAddress() { return address; } public void setAddress(String address) { this.address = address; } } MANIFEST.MF Manifest-Version: 1.0 Class-Path: persistence.xml <?xml version="1.0" encoding="UTF-8"?> <persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"> <persistence-unit name="SimpleJPA5"> <class>com.jpa.test.User</class> <properties> <property name="eclipselink.jdbc.user" value="root" /> <property name="eclipselink.jdbc.password" value="roded75" /> <property name="eclipselink.jdbc.url" value="jdbc:mysql://localhost:3306/test" /> <property name="eclipselink.jdbc.driver" value="com.mysql.jdbc.Driver" /> <property name="eclipselink.ddl-generation" value="drop-and-create-tables" /> </properties> </persistence-unit> </persistence> Java SE Client import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory; import javax.persistence.Persistence; public class Test { /** * @param args */ public static void main(String[] args) { User aUser = new User();
aUser.setName(”John John”); aUser.setZip(”123456�); aUser.setAddress(”CA sun blvrd”); EntityManagerFactory emf = Persistence.createEntityManagerFactory(”SimpleJPA5�);
EntityManager em = emf.createEntityManager();
em.getTransaction().begin(); em.persist(aUser); em.getTransaction().commit(); em.close(); emf.close(); System.out.println(”Done”);
} } Author:adminCategories:Common Java, JPATags:J2SE, JPA
Simple Time Out Wrapper December 1st, 2009 A simple time out wrapper can be achieved in the following way: //Set a timer to throw interruption when timeout Timer timer = new Timer(); timer.schedule(new InterruptScheduler(Thread.currentThread()), timeOutValueInMillis); try { //Your code Here... } catch (InterruptedException e) { //Interruption Occured - Handle... } finally { // Stop the timer timer.cancel(); } Author:adminCategories:Common JavaTags:J2SE, Timeout, Timer
Monitoring Java Process (for example JBoss) August 9th, 2009 No comments
Since JDK 1.5 a monitoring tool is available. JConsole.exe resides under jdk/bin.
In order to use it just use the following vm argument when running a java process (jboss, yourJar.jar, …):
Just add the vm argument: -Dcom.sun.management.jmxremote
for example: in JBoss run.bat add the following line:
rem Run with managed VM in order to allow Monitoring via JMX
set JAVA_OPTS=%JAVA_OPTS% -Dcom.sun.management.jmxremote
In order to identify the Java process of the Jboss started use:
the jps utility (Also resides under jdk/bin): jps -l
Example outpout:
4384 org.jboss.Main
2172
3644 sun.tools.jps.Jps
3456 Tray
Author:adminCategories:Common Java, MonitoringTags:JBOSS, JConsole, JPS, Monitoring
Read Text File with Java July 13th, 2009 No comments
Read a Text File with java BufferedReader class
public static void main(String[] args) throws Exception {
String filePath = "c:\\temp\aTextFile.txt";
try {
BufferedReader input = new BufferedReader(new FileReader(filePath));
try {
String line = null;
while ((line = input.readLine()) != null) {
if (line != null) {
handleLine(line);
}
}
} finally {
input.close();
}
} catch (Exception e) {
e.printStackTrace()
}
}
Author:adminCategories:Common JavaTags:java
Iterating Lists Complexity Issues March 17th, 2009 No comments
Iterating a list in order to find a specific item is a pretty common task.
Lets take the following code example:
Problem: Lets say we have the following example:
import java.util.Vector; public class CodeReview { public static void main(String[] args) { Vector items = new Vector(); Vector itemsToBeRemoved = new Vector(); items.add("A"); items.add("B"); items.add("C"); itemsToBeRemoved.add("B"); new CodeReview().removeItems(items, itemsToBeRemoved); System.out.println(items); } private void removeItems(Vector items, Vector itemsToBeRemoved) { for (Object anItem : itemsToBeRemoved) { //Remove or if not exist will keep unchanged items.remove(anItem); } } }
This simple code hides a performance issue which might not be noticed while implementing business logic under a stressed deadline.
Why? Lets assume we have list1 with n items and list2 with m items. The complexity of finding an item will be n*m = n^2. This might be innocent in some cases or a total disaster in other cases. Solution: The first thing comes in mind is to use some sort of a Map and this is the correct.
As the cost of at least n complexity will be “paid”, instead of keep on using the remove method (with n complexity) at each iteration (leading n*m complexity) a conversion of the list to a Map (initially or while iterating) instance will optimize the complexity into complexity of n . If we will use for example a LinkedHashSet the complexity then will be n*1 using the item as key. This is a very simple solution that might optimize performance, in some cases even dramatically.
Summary: while using any the method contains or remove an algorithm with n complexity is used. This might make iterations and sub interations very expensive. Where memory is not an issue keep in mind the conversion to Map instance when you can. �
�
Relaationshipps
�
�
�
�
�
��
�
�
�
Concurrency (Locking) Mode OC4J also provides concurrency modes for handling resource contention and parallel execution within EJB 3.0 entities and EJB 2.1 entity beans with container-managed persistence.
Entity beans with bean-managed persistence manage the resource locking within the bean implementation themselves.
Concurrency modes include the following:
� 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:
� If the values are the same, TopLink updates the version field in the object and commits the changes to the data source.
� If the values are different, the write operation is disallowed because another client must have updated the object since this client initially read it.
� 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.
� 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
Goals fo
� Ath
� Aaudre
� Au
�
xceptions
or Exceptio
An applicatiohe client PRE
An applicatioutomaticallyefined to cauecover a tran
An unexpecteunderlying pe
s
on Handlin
n exception tECISELY (i.en exception ty rollback a use transactnsaction fromed exceptionersistent dat
ng
thrown by ae., the clientthrown by aclient's trantion rollbackm an applica
n that may hta in an inco
an enterpriset gets the SAan enterprisensaction unlek. The clientation except
have left the onsistent sta
e bean instaAME exceptioe bean instaess the applt should typition. instance's sate can be h
�
ance should on).
ance should lication exceically be give
state variablehandled safel
be reported
NOT eption was en a chance
es and/or ly.
to
to
Message-driven Beans
Let's now look at the final type of EJB: message-driven beans.
Business interface The business interface of a message-driven bean (MDB) is the message-listener interface that is determined by the messaging type in use for the bean. The interface is javax.jms.MessageListener. The message-driven bean must implement the appropriate message listener interface for the messaging type that the message-driven bean supports or must designate its message-listener interface using the@MessageDriven annotation or the deployment descriptor. Bean class In EJB 3.0, the MDB bean class is annotated with the @MessageDriven annotation, which specifies the message queue this MDB monitors (such as queue/mdb).
The bean class needs to implement the MessageListener interface, which defines only one method, onMessage(). When a message arrives in the queue monitored by this MDB, the container calls the bean class's onMessage() method and passes the incoming message in as the call parameter.
In our example, the TraderBean.onMessage() method retrieves the message body, parses out the parameters, performs the trade, and saves the result to a static data manager class. The "sent" timestamp on the service request message serves as the unique ID for the calculation record (it works well for low-volume Web sites). A check.jsp JSP page picks up and displays the calculation record based on the message ID:
@MessageDriven(activateConfig = { @ActivationConfigProperty(propertyName="destinationType", propertyValue="javax.jms.Queue"), @ActivationConfigProperty(propertyName="destination", propertyValue="queue/mdb") }) public class TraderBean implements MessageListener { public void onMessage (Message msg) { try { TextMessage tmsg = (TextMessage) msg; Timestamp sent = new Timestamp(tmsg.getLongProperty("sent")); StringTokenizer st = new StringTokenizer(tmsg.getText(), ","); buy ("SNPS",1000); RecordManager.addRecord (sent, "BUY SUCCESSFUL"); } catch (Exception e) { e.printStackTrace (); } } // ... ... }
Sending To use ththe standname (qutry { InitialC queue = QueueC (Queu cnn = fa sess = c fa} catch (E e.print} TextMesssender = sender.se
CallbackThe follow
� P� P
Messag
Impleme
Configur
Configur
Configur
a message he message-dard JMS APueue/mdb),
ontext ctx == (Queue) ctxConnectionFeConnectionactory.createcnn.createQualse,QueueSException e) tStackTrace
sage msg = ssess.createS
end(msg);
ks for messawing life cycostConstrucreDestroy
e Service C
enting an E
ring an EJB
ring an EJB
ring Paralle
driven beanPI to obtain and then it
new InitialCx.lookup("qu
Factory factonFactory) ctxeQueueConnueueSessionession.AUTO{ ();
sess.createTSender(queu
age-driven bcle event callct
Configurat
JB 3.0 MDB
B 3.0 MDB t
B 3.0 MDB t
l Message P
n, the client (the target msends the m
Context(); ueue/mdb");ory = x.lookup("Conection(); n( O_ACKNOWL
TextMessageue);
beans lbacks are s
tion Optio
B
o Access a
o Access a
Processing
(such as themessage queumessage to th
;
onnectionFa
LEDGE);
("SNPS",100
upported for
ns
Message Se
Message Se
e JSP page, tue to the MDhe queue:
actory");
00);
r message-d
ervice Provi
ervice Provi
trader.jsp, inDB by way o
driven beans
ider Using J
ider Directly
n this case) of the queue
s:
J2CA
y
uses
Configuring Maximum Delivery Count
Configuring Connection Failure Recovery for an EJB 3.0 MDB
Configuring a Life Cycle Callback Interceptor Method on an EJB 3.0 MDB
Using Annotations You can specify an EJB 3.0 message-driven bean class method as a life cycle callback method using any of the following annotations:
� @PostConstruct � @PreDestroy
Configuring a Life Cycle Callback Interceptor Method on an Interceptor Class of an EJB 3.0 MDB
Using Annotations You can specify an interceptor class method as an EJB 3.0 message-driven bean life cycle callback method using any of the following annotations:
� @PostConstruct � @PreDestroy
Configuring an Around Invoke Interceptor Method on an EJB 3.0 MDB
Configuring an Around Invoke Interceptor Method on an Interceptor Class of an EJB 3.0 MDB
Configuring an Interceptor Class for an EJB 3.0 MDB
Configuring OC4J-Proprietary Deployment Options on an EJB 3.0 MDB
Understanding Message Services
A message service provider is responsible for providing a destination to which clients can send messages and from which message-driven beans can receive messages for processing.
OC4J supports a variety of message service providers for both XA-enabled two-phase commit (2PC) and non-XA enabled transactions.
You can access a message service provider directly or by way of a J2EE Connector Architecture (J2CA) resource adapter such as Oracle JMS Connector.
You can use JNDI to look up and retrieve these components using the following:
� JNDI initial context � EJB context � EJB 3.0 annotations and resource injection
Understanding EJB Timer Services You can set up a timer that invokes a timeout callback method at a specified time, after a specified elapsed time, or at specified intervals.
Note: Timers apply to all EJB types except stateful session beans and EJB 3.0 entities.
For EJB 3.0 applications, using the @Timeout annotation, you can annotate any EJB method as the timeout callback method.
For EJB 2.1 applications, your EJB must implement the TimedObject interface and provide a timeout callback method namedejbTimeout.
Timers are for use in modeling of application-level processes, not for real-time events.
OC4J provides standard Java EE timers as well as a convenient Java EE timer extension that allows configuration similar to the Unix cron utility.
Timer and timeout callback methods should be called within a transaction. OC4J supports transaction attribute REQUIRES_NEW for timeout callbacks. For more information on transaction attributes, see "How are Transactions Handled When a Client Invokes a Business Method?").
An enterprise bean accesses EJB timer services by means of dependency injection, through the EJBContext interface, or through lookup in the JNDI namespace.
Understanding Java EE Timer Services The EJB timer service is a container-managed service you use to define callback methods on your EJB that are scheduled for time-based events. The EJB timer service provides a reliable and transactional notification service for timed events. Timer notifications may be scheduled to occur at a specific time, after a specific elapsed duration, or at specific recurring intervals. You can define callback methods on your EJB to receive these time-based events. The Java EE timer service is implemented by OC4J
Understanding OC4J Cron Timer Services In UNIX, you can schedule a cron timer to execute regularly at specified intervals. Oracle has extended OC4J to support cron timers with EJB. You can use cron expressions for scheduling timer events with EJB deployed to OC4J. Using an OC4J cron timer, you can create timers that invoke a timeout callback method or any arbitrary Java class's main method. Understanding EJB Data Source Services { Managed Data Source Native Data Source } ���
Who Manages a Transaction? A transaction can be managed by either the container or the bean Container-managed transaction management is the default.
When configuring transaction management for your enterprise beans, consider the following restrictions:
� EJB 3.0 entities cannot be configured with a transaction management type. EJB 3.0 entities execute within the transactional context of the caller.
� EJB 2.1 entity beans must always use container-managed transaction demarcation. An EJB 2.1 entity bean must not be designated with bean-managed transaction demarcation.
For all other EJB types, you can choose either container-managed or bean-managed transaction management. What are Container-Managed Transactions? When you use container-managed transactions (CMT), your EJB delegates to the container the responsibility to ensure that a transaction is started and committed when appropriate. All session and message-driven beans may use CMT. EJB 2.1 entity beans must use CMT. EJB 3.0 entities cannot be configured with a transaction management type. EJB 3.0 entities execute within the transactional context of the caller.
When developing an enterprise bean that uses CMT, consider the following:
� Do not use resource manager-specific transaction management methods such as java.sqlConnection methods commit,setAutoCommit, and rollback or javax.jms.Session methods commit or rollback.
� Do not obtain or use the javax.transaction.UserTransaction interface. � A stateful session bean using CMT may implement
the javax.ejb.SessionSynchronization interface. � An enterprise bean that uses CMT may
use javax.ejb.EJBContext methods setRollbackOnly and getRollbackOnly.
For an EJB that uses CMT, for each business method, you can also specify a transaction attribute that determines how the container manages transactions when a client invokes the method.
�
�
���
What are Bean-Managed Transactions? When you use bean-managed transactions (BMT), the bean-provider is responsible for ensuring that a transaction is started and committed when appropriate.
Only session and message-driven beans may use BMT.
When developing an EJB that uses BMT, consider the following: � Use the javax.transaction.UserTransaction methods begin and commit to demarcate
transactions.
� 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.
� A stateless session bean instance must commit any transactions that it started before a business method or timeout callback method returns.
� A message-driven bean instance must commit a transaction before a message listener method or timeout callback method returns.
� After starting a transaction, do not use resource-manager specific transaction
management methods such as java.sqlConnectionmethods commit, setAutoCommit, and rollback or javax.jms.Session methods commit or rollback.
� A bean that uses BMT must not use EJBContext methods getRollbackOnly and setRollbackOnly. It must useUserTransaction method getStatus and rollback instead.
How are Transactions Handled When a Client Invokes a Business Method?
For an enterprise bean that uses CMT (see "What are Container-Managed Transactions?"), you can specify a transaction attribute that determines how the container must manage transactions when a client invokes a bean method.
You can specify a transaction attribute for each of the following types of bean method:
� a method of a bean's business interface; � a message listener method of a message-driven bean; � a timeout callback method; � a stateless session bean's Web service endpoint method; � for EJB 2.1 and earlier, a method of a session or entity bean's home or component
interface
Table 2-6 shows what transaction (if any) an EJB method invocation uses depending on how its transaction attribute is configured and whether or not a client-controlled transaction exists at the time the method is invoked.
OC4J starts a container-controlled transaction implicitly to satisfy the transaction attribute configuration when a bean method is invoked in the absence of a client-controlled transaction.
Table 2-
TransactAttribute
Not Supp
Supports
Required
Requires
Mandato
Never
How do If all resocoordina
The midd
� an� in� la� re
UnderstYou can the follow
� J� J
-6 EJB Tran
tion e C
ported C
s U
dFoot 1 U
New Ca
ry U
E
You Particiources enlistates a global
dle-tier coord
ny XA-compnterpositioniast resource ecovery loggi
tanding EJconfigure yo
wing: ava 2 Securava Authent
nsaction Su
Client-Cont
Container su
Use client-co
Use client-co
Container suand starts a
Use client-co
Exception ra
ipate in a Gted in a tranor two-phas
dinator supp
pliant resouring and trancommit opting;
JB Securityour EJB to u
ity Model; tication and
upport by Tr
rolled Tran
uspends the
ontrolled tra
ontrolled tra
uspends the new transac
ontrolled tra
aised
Global or Twnsaction are se commit tr
ports the fol
rce; nsaction inflotimization;
y Services use the Java
Authorizati
ransaction
saction Exi
client trans
ansaction
ansaction
client transction
ansaction
wo-Phase CoXA-complia
ransaction.
llowing:
ow;
a EE security
on Service (J
Attribute
ists CliTra
saction Us
Us
Cotra
saction Cotra
Exc
Us
ommit (2PCant, then OC
y services th
JAAS);
ient-Controansaction D
e no transac
e no transac
ntainer staransaction
ntainer staransaction
ception rais
e no transac
C) TransactiC4J automat
hat OC4J pro
olled Does Not Ex
ction
ction
rts a new
rts a new
ed
ction
ion? tically
ovides, inclu
xist
uding
Exceptions from a Session Bean's Business Interface Methods
� 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 condition Method exception Container's action Client's view
Bean method runs in the context of the caller's transaction. The caller can be another enterprise bean or an arbitrary client program. This case may happen withRequired,Mandatory, andSupportsattributes.
Application Exception
Re-throw Application Exception. Mark the transaction for rollback if the application exception is specified as causing rollback.
Receives Application Exception. Can attempt to continue computation in the transaction, and eventually commit the transaction unless the application exception is specified as causing rollback (the commit would fail if the instance called setRollbackOnly).
all other exceptions
Log the exception or error (so that the System Administrator is alerted of the problem).
Mark the transaction for rollback.
Discard instance (so that the container must not invoke any business methods or container callbacks on the instance).
Throwjavax.ejb.EJBTransactionRolledbackException to client. If the business interface is a remote business interface that extends java.rmi.Remote, thejavax.transaction.TransactionRolledbackExceptionis thrown to the client, which will
Receivesjavax.ejb.EJBTransactionRolledbackException.
Continuing transaction is fruitless.
Method condition Method exception Container's action Client's view
receive this exception.
Bean method runs in the context of a transaction that the container started immediately before dispatching the business method.
This case may happen withRequired andRequiresNewattributes.
Application Exception
If the instance called setRollbackOnly(), then rollback the transaction, and re-throw Application Exception.
Mark the transaction for rollback if the application exception is specified as causing rollback, and then re-throw Application Exception.
Otherwise, attempt to commit the transaction, and then re-throw Application Exception.
Receives Application Exception.
If the client executes in a transaction, the client's transaction is NOT marked for rollback, and client can continue its work.
all other exceptions
Log the exception or error.
Rollback the container-started transaction.
Discard instance.
Throw EJBException to client. If the business interface is a remote business interface that extendsjava.rmi.Remote, the java.rmi.RemoteException is thrown to the client, which will receive this exception.
Receives EJBException.
If the client executes in a transaction, the client's transaction may or may not be marked for rollback.
Bean method runs with an unspecified transaction context.
This case may happen with with theNotSupported,Never
Application Exception
Re-throw Application Exception.
Receives Application Exception.
If the client executes in a transaction, the client's transaction is NOT marked for rollback, and client can continue its work.
Method condition Method exception Container's action Client's view
, andSupportsattributes.
all other exceptions
Log the exception or error.
Discard instance.
Throw EJBException to client. If the business interface is a remote business interface that extendsjava.rmi.Remote, the java.rmi.RemoteException is thrown to the client, which will receive this exception.
Receives EJBException.
If the client executes in a transaction, the client's transaction may OR may not be marked for rollback.
� Table below specifies how the container must handle the exceptions thrown by the methods of the business interface for beans with bean-managed transaction (BMT) demarcation, including the exceptions thrown by business method interceptor methods which intercept the invocation of business methods. The table specifies the container's action as a function of the condition under which the business interface method executes and the exception thrown by the method. The table also illustrates the exception that the client will receive and how the client can recover from the exception.
Table 10.2. Handling of Exceptions Thrown by a Business Interface Method of a Session Bean with Bean-Managed Transaction Demarcation
Bean method
condition Bean method
exception Container action Client receives
Bean is stateful or stateless session.
Application Exception
Re-throw Application Exception. Receives Application Exception.
all other exceptions
Log the exception or error.
Mark for rollback a transaction that has been started, but not yet completed, by the instance.
Discard instance.
Throw EJBException to client. If the business interface is a remote business interface that extendsjava.rmi.Remote, thejava.rmi.RemoteException is thrown to the client, which will receive this exception.
Receives EJBException.
Exceptions from Message-Driven Bean Message Listener Methods
� Table below specifies how the container must handle the exceptions thrown by a message listener method of a message-driven bean with container-managed transaction (CMT) demarcation, including the exceptions thrown by business method interceptor methods which intercept the invocation of message listener methods. The table specifies the container's action as a function of the condition under which the method executes and the exception thrown by the method.
Table 10.3. Handling of Exceptions Thrown by a Message Listener Method of a Message-Driven Bean with Container-Managed Transaction Demarcation
Method condition Method exception Container's action
Bean method runs in the context of a transaction that the container started immediately before dispatching the method.
This case happens with the Required attribute.
Application Exception
Mark the transaction for rollback if the application exception is specified as causing rollback.
If the instance called setRollbackOnly, rollback the transaction and re-throw Application Exception to resource adapter.
Otherwise, attempt to commit the transaction unless the application exception is specified as causing rollback and re-throw Application Exception to resource adapter.
system exceptions
Log the exception or error (so that the System Administrator is alerted of the problem).
Rollback the container-started transaction.
Discard instance (so that the container must not invoke any methods on the instance).
Throw EJBException that wraps the original exception to resource adapter.
Bean method runs with an unspecified transaction context.
This case happens with the NotSupportedattribute.
Application Exception Re-throw Application Exception to resource adapter.
system exceptions
Log the exception or error.
Discard instance.
Throw EJBException that wraps the original exception to resource adapter.
� 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 10Driven B
Bean mcondi
Bean is message-bean
javax.ejb
0.4. HandlinBean with Be
method ition
-driven
Ap
sy
b.SessionSy
ng of Exceptean-Manage
Bean metexceptio
pplication Ex
stem except
ynchronizati
tions Throwed Transacti
thod on
xception R
tions
Lo
Mst
D
Thex
ion Interfac
n by a Mession Demarca
e-throw App
og the excep
Mark for rollbtarted, but n
iscard insta
hrow EJBExxception to r
e
sage Listeneation
Contain
plication Exc
ption or erro
back a transnot yet comp
ance.
xception tharesource ada
er Method of
ner action
ception to re
r.
saction that pleted, by th
at wraps the apter.
f a Message
esource adap
has been he instance.
original
�
e-
pter.
Begin tran
Commit t
nsaction sequ
ransaction se
uence:
equence:
UML Di
�
�
�
�
iagram
�
DB Design
�
�