Login | Register   
LinkedIn
Google+
Twitter
RSS Feed
Download our iPhone app
TODAY'S HEADLINES  |   ARTICLE ARCHIVE  |   FORUMS  |   TIP BANK
Browse DevX
Sign up for e-mail newsletters from DevX


advertisement
 

The Java EE Application as an EJB/Spring/Hibernate Hybrid : Page 4

Java EE 5 provides all the features you need to build a robust enterprise application right in an EJB 3.0 container, but incorporating the relative strengths of Spring and Hibernate can further improve the productivity and quality of your application.


advertisement
Implementing Hibernate JPA Using Spring
EJB 3.0 comes with JPA, a robust ORM-based persistence solution. Because it is an open standard, JPA allows developers to choose an alternate implementation using a JPA-compatible tool. Hibernate is one such tool. Spring has traditionally supported Hibernate with its DAO support classes and recently started supporting JPA. You will combine these into a Spring-driven JPA implementation using Hibernate.

Of course you can use a container-supported JPA implementation, but you would forgo significant added features that Hibernate offers. Hibernate's configuration-based features such as locking, caching, and dynamic updates can provide substantial value in terms of productivity and performance without tying the application code to Hibernate. If portability is not necessarily a concern, Hibernate also provides a slew of options in its API, mappings, and annotations that go far beyond what JPA provides for integrating with complex enterprise databases.

Hibernate also benefits from integrating with JPA as opposed to being a standalone implementation. The significant value-adds of being in a Java EE container include portable queries, integration into a life cycle with other application components, automatic transaction demarcation, automatic detection of annotated classes, ease of deployment, and consistent interfaces.



Using Spring to implement persistence though Hibernate not only provides Spring features such as interceptors, extensive AOP support, product integration, granular transactions, and non-intrusive lightweight dependency management, but it also allows you to transparently leverage the features of Hibernate's strong, specification-based ORM implementation. To begin, create the Listing 1 entry in domainContext.xml. Here is a quick explanation of the significant elements:

  • The "entityManagerFactory" ID is used to create an entity manager, which the DAO classes subsequently will use for persistence.
  • The EntityManager instance in JPA is used to manage the life cycle of entities within a persistence context. It basically finds entities with keys, creates them, and removes them.
  • It is also used to execute queries. You leverage LocalContainerEntityManagerFactoryBean, a Spring wrapper, to instantiate the JPA EntityManager and provide other fine-grained options such as custom JPA providers.
  • This is where you declare your intention to use Hibernate as your JPA service provider and set its properties.
  • The database dialect is configured through the "databasePlatform" parameter. (Optionally, for popular databases you can also add the parameter "database." For more information, see JavaDocs of org.springframework.orm.jpa.vendor.HibernateJpaVendorAdapter.)
  • The entry also takes a datasource as a parameter. The datasource can be either procured through JNDI or, as in this case, declared locally.
  • There is also an optional entry for loadTimeWeaver, which is set specifically to the container and is sometimes required if the persistence provider insists on support for byte-code transformation. Hibernate does not require such an entry.
  • The entry also declares a transaction manager and enables annotation-based transaction support in your classes. It looks for the @Transactional tag. PersistenceExceptionTranslationPostProcess is a Spring value-add used to facilitate exception translation to a provider-specific exception instead of the standard JPA exception hierarchy. It looks for the @Repository tag.
  • The JPA specification requires the presence of a file called persistence.xml in the META-INF directory. This file is typically where you would have added the reference to a Hibernate implementation and added Hibernate-specific properties. However, because Spring has taken over the function of supporting a JPA vendor, all entries go in the domainContext and you can ignore them here.

Your file ends up looking as follows, with only the definition of a persistence unit name:

<persistence 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" version="1.0"> <persistence-unit name="persistenceunit"> </persistence-unit> </persistence>

You will also define an entity class called com.app.domain.entity.Profile, which is nothing but a POJO. You can instantiate it with new. It is a non-abstract, concrete class that has no dependencies on anything related to the container. You can wholly specify the persistence nature of the entity by using annotations. The following are the significant parts of the class:

@Entity @Table(name="APP.PROFILE") public class Profile implements Serializable{ @Id @Column(name="PROFILEID") private String id; @Column(name="FNAME") private String fname; @Column(name="LNAME") private String lname; @Column(name="ADDRESS") private String address; @Column(name="EMAIL") private String email; // bunch of getters/setters ... }

The declaration @Entity has denoted this as a class that will be persisted. The @Table definition lists the table name of the database referenced. The @ID field denotes the primary key of the table, and all other annotations map the class variable to the corresponding database column. This class is fully self sufficient, and you can persist it. You will use it to build a relationship with the database, carry data to and from the database, and (because it's a POJO) pass around information across tiers.

Now you're at the implementation of the Data Access Object (also called the Entity Access Object) class, which is responsible for the actual actions related to persistence. At this point, you have a couple of choices:

  1. You can implement the whole class with standard JPA constructs, completely independent of Spring.
  2. You can leverage Spring and use its JPATemplate class through its JpaDaoSupport helper class.

If you choose not to use JPATemplate, the EntityManager is passed on to the DAO using the annotation @PersistentContext. In a regular JPA, the container would populate the EntityManager using dependency injection. In this case, Spring plays that role. Spring recognizes JPA constructs such as @PersistentContext and injects the EntityManager just like the container. The PersistenceAnnotationBeanPostProcessor, declared in Spring context, helps with the JPA annotation processing. However, even though the code is independent of any Spring classes, it also means that the DAO now has to worry about the EntityManager life cycle and transactions. Spring can still help in granular transaction management using the @Transactional annotation. The class com.app.domain.dao.impl.HibernateProfileDaoNonTmpl shows an example of such an implementation.

For your implementation, you will extend the Spring JpaDaoSupport helper class and use the JPATemplate provided as getter/setter methods. The JPATemplate, in the tradition of HibernateTemplate and JDBCTemplate, takes over the responsibility of managing the state of EntityManager, automatically participates in transactions, and manages exceptions. It also offers all the underlying methods supported by JPA and provides some more convenient methods to improve productivity. It is thread-safe as well, and you can use it as an instance variable.

The declaration and the DAO code look like this:

@Transactional public class HibernateProfileDao extends JpaDaoSupport implements ProfileDao { public Profile getProfile(String id) { Profile pro = getJpaTemplate().find(Profile.class, id); return pro; } public long setProfile(Profile p) { if (p.getId() == null) { // insert new record getJpaTemplate().persist(p); } else { // update existing record after a read getJpaTemplate().merge(p); } return 0; } }

Again, the @Transactional notation ensures transaction management and commits/rollbacks.

The resulting EJB domain project tree should look like Figure 3.

Click to enlarge

Figure 3. EJB Domain Project Tree:
Here is how your EJB domain project tree should look.



Comment and Contribute

 

 

 

 

 


(Maximum characters: 1200). You have 1200 characters left.

 

 

Sitemap