Login | Register   
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
 

Make the Right Decision with Our Side-by-Side Comparison of Spring and EJB 3.0 : Page 2

Are you trying to choose between Spring and EJB 3.0? If you are you know what a hard decision it can be. Explore the similarities and differences between two of the most popular Java technologies today and learn key distinctions in making a technological decision between the two.


advertisement
Persistence
Persistence is a critical component of any enterprise application. And not surprisingly both Spring and EJB 3.0 provide robust support for it. True to its design philosophy, Spring doesn't re-implement a persistence framework but rather integrates with many popular ones including JDBC, Hibernate, JDO, iBatis, and (as of Spring 2.0) the Java Persistence API (JPA). With the EJB 3.0 specification entity beans have been replaced with the JPA.

JPA aims to provide a simplified, light-weight, object-relational mapping framework. This specification (a separate document within the EJB 3.0 specification) defines interfaces for interacting with the persistence provider and for mapping entities to a relational database.

Persistence—Functional Comparison
To illustrate the comparability in support between Spring and EJB 3.0 consider the domain model for the flight booking application shown in Figure 1.



Figure 1. Flight Booking Domain Model. The flight booking domains illustrated many interesting ORM concepts such as composition, bi-directionality, and ternary associations.
The unit test below verifies that a ticket can be created, associated with existing flights, seats assigned, and saved to a database:

public void testSave() { Ticket ticket = TicketMother.create(); Flight outboundFlight = flightDAO.findById(1); Flight returnFlight = flightDAO.findById(2); ticket.setOutboundFlight(outboundFlight); ticket.setReturnFlight(returnFlight); ticket.getPassenger().setFlightDetails(outboundFlight, new PassengerFlightDetails(getSeatForFlight(outboundFlight, "2A"))); ticket.getPassenger().setFlightDetails(returnFlight, new PassengerFlightDetails(getSeatForFlight(returnFlight, "2B"))); ticketDAO.save(ticket); ticket = ticketDAO.findById(ticket.getId()); assertEquals("John", ticket.getPassenger().getFirstName()); assertEquals("2A", ticket.getPassenger().getDetailsForFlight(ticket.getOutboundFlight()) .getSeat().getNumber()); }

This test can be run successfully against both Spring and EJB 3.0 implementations indicating that the two technologies have functionally equivalent support for basic ORM persistence. The two implementations are also very similar. I have chosen to illustrate the Spring implementation with Hibernate since it is the most common ORM provider used in conjunction with Spring and because JPA support is not available in the current production release of Spring. A Spring/Hibernate implementation of the TicketDAO is class is illustrated below:

public class TicketSpringDAO extends HibernateDaoSupport implements TicketDAO { public Ticket save(Ticket ticket) { getHibernateTemplate().saveOrUpdate(ticket); return ticket; } ... }

And the corresponding EJB 3.0 implementation is seen here:

@Stateless public class TicketEJBDAO implements TicketDAO { @PersistenceContext(unitName = "flightdb") private EntityManager em; public Ticket save(Ticket ticket) { em.persist(ticket); return ticket; } ... }

Obviously these implementations are both very similar. In the Spring implementation the details of working with Hibernate are abstracted away by the HibernateDaoSupport class, which provides the Hibernate plumbing and assists in working with the Spring Hibernate template and dependencies. In the EJB 3.0 implementation the entity manager is automatically injected by the container.

The Hibernate Session and the JPA Entity Manager are roughly equivalent but there are a couple of important differences to keep in mind. The Hibernate session is an entity cache as well an interface into the ORM engine. In JPA these two concepts are separated. The persistence context functions as the cache while the entity manager functions at the interface into the ORM engine.

It is also interesting to notice the different approaches towards mapping persistence entities to their relational equivalents. The Spring/Hibernate mapping is expressed in the following XML mapping file:

<hibernate-mapping package="org.jug.flight.domain" default-lazy="false"> <class name="Ticket"> <id name="id" column="id"> <generator class="native" /> </id> <property name="status" type="Status" /> <many-to-one name="outboundFlight" column="outbound_flight" /> <many-to-one name="returnFlight" column="return_flight" /> <many-to-one name="passenger" column="passenger_id" cascade="all" /> </class> </hibernate-mapping>

JPA applications often choose to use annotations to express this mapping because it reduces the configuration required, keeps the mapping data close to the objects it modifies, and enhances visibility. This approach is illustrated below:

@Entity public class Ticket implements Serializable { @Id @GeneratedValue private long id; private Status status; private double price; @ManyToOne(cascade = CascadeType.PERSIST) private Passenger passenger; private Flight outboundFlight; private Flight returnFlight; ... }

As you can see, Spring/Hibernate and EJB 3.0/JPA offer roughly functionally equivalent support for persistence via ORM.

Persistence—Non-Functional Comparison
The primary difference between Spring and EJB 3.0's support for persistence may at first appear to be compatibility with different persistence frameworks. Spring provides support for many different ORM implementations. In EJB, only JPA is explicitly supported. But it is important to remember that JPA is merely a specification and many different providers support JPA including Hibernate, Kodo, and TopLink. Table 1 lists the default JPA provider for several popular EJB 3.0 application servers:

Table 1. JPA Providers Supported by Leading App Servers.

Application Server JPA Implementation
JBoss Hibernate
BEA Kodo (OpenJPA)
Oracle TopLink
Glassfish TopLink

In this sense both technologies offer a choice in persistence providers. If you need to use provider-specific features that are not part of the JPA specification then you can certainly do so in your EJB application but you may sacrifice platform cross-compatibility.

Another important concept when working with ORM tools is caching. The cache is important when considering Spring and EJB 3.0 because in order for multiple components to collaborate on a single unit of work this cache must be shared between them. In Spring this is typically accomplished by applications attaching the session (and transaction) to the thread using thread local variables. Although Spring offers classes to make implementing this easier it still needs to be addressed by the development team. In EJB 3.0 by contrast the persistence context is propagated automatically on the transaction.

Object models are often rich and complex graphs. It would be inefficient if every time a persistent entity was retrieved from the database if all of its relationships were automatically fetched. To address this ORM providers often provide functionality such as lazy initialization, which defers the execution of particular database operations until the data is actually needed. This prevents a lot of unnecessary and expensive database calls but can complicate application logic quite a bit. If the cache associated with a lazily initialized collection is closed when the collection is accessed then exceptions are thrown.

The approach taken by Spring/Hibernate is to open and close the cache around view creation. Spring provides an OpenSessionInViewFilter (and interceptor) to simplify this, but it must be configured. The EJB 3.0 specification adds an interesting scope to its persistence context that allows the lifetime of the cache to be bound to the lifetime of a stateful session bean. This is named an extended persistence context and is specified by annotating the persistence context in the stateful session bean. This can simplify working with long application transactions and lazily loaded collections.

Persistence—Summary
Because JPA supports pluggable persistence providers and because Spring supports those same providers directly these two approaches are very comparable. Table 2 highlights the major comparison points.

Table 2. Summation of Persistence Comparison Between Spring and EJB 3.0.

Feature Spring EJB 3.0
Simple ORM Persistence
Implementation Hibernate, JPA, JDO, TopLink, iBatis JPA (providers include Hibernate, Kodo and Toplink)
JDBC Support --
Mapping XML, Annotations Annotations, XML
Cache Propagation Thread local Transaction
Extended cache scoping Open session in view Extended persistence context
Standard √ (If using JPA)



Comment and Contribute

 

 

 

 

 


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

 

 

Sitemap