3.2.3. Persistence Layer
In the persistence layer you've a several strategic options, in this chapter we'll cover EJB, Hibernate and JPA. In the sections below we'll look at some examples and approaches how to implement this layer.
The version of the JDK plays an important role in what you can choose. Hibernate with annotations and JPA depend on the annotations support within JDK5. This means that if you're still using previous versions of the JDK, your options are limited to Hibernate core or Hibernate with XDoclet. Spring DAO support only needs JDK 1.3 (or higher) so this is always a highly recommended option.
As a code example we'll persist a Customer domain object using the different technologies, resulting in a Customer POJO class displayed below.
import java.util.Set;
import java.util.Collections;
public class Customer {
private long id;
private String name;
private Set orders = Collections.EMPTY_SET;
public Customer() {
}
public long getId() {
return(id);
}
public void setId(long lId) {
id = lId;
}
public String getName() {
return(name);
}
public void setName(String sName) {
name = sName;
}
public Set getOrders() {
return(orders);
}
public void setOrders(Set oOrders) {
orders = oOrders;
}
}
Enterprise Java Beans (EJB) 2.x
Because of the complexity of EJB 2.x different open source initiatives were created resulting with the known dominance of Hibernate and the Spring Framework. In a later phase EJB3 and JPA resulted as a standardized JCP 'reaction' to Hibernate and Spring.
Hibernate
Hibernate
has evolved in different stages where today we have Hibernate Core and Hibernate Annotations.
However an intermediate step between the two Hibernate approaches is the usage of XDoclet. XDoclet
is a code generation engine and uses custom JavaDoc-like tags to generate external resource files, lets say the ancestor of Annotations. The advantage of XDoclet is that JDK5 is not needed making it a perfect transition strategy towards Hibernate Annotations and eventually JPA.
Hibernate Core
Hibernate with XDoclet
Hibernate XDoclet allows you to add java-doc styled persistent comments to your classes.
import java.util.Set;
import java.util.Collections;
/** A business entity class representing an Acme Company customer.
*
* @hibernate.class table="customers"
*/
public class Customer {
/** This Customer's identifier field.
*/
private long id;
/** This Customer's name field.
*/
private String name;
/** The customer's orders set.
*/
private Set orders = Collections.EMPTY_SET;
/** The default construtor for Hibernate to instantiate with.
*/
public Customer() {
}
/** The getter method for this Customer's identifier.
*
* @hibernate.id generator-class="native"
*/
public long getId() {
return(id);
}
/** The setter method for this Customer's identifier.
*/
public void setId(long lId) {
id = lId;
}
/** The getter method for this Customer's name
*
* @hibernate.property
*/
public String getName() {
return(name);
}
/** The setter method for this Customer's name.
*/
public void setName(String sName) {
name = sName;
}
/** The getter method for this Customer's orders.
*
* @hibernate.set role="orders"
*
* @hibernate.collection-key column="customer_id"
*
* @hibernate.collection-one-to-many class="Order"
*/
public Set getOrders() {
return(orders);
}
/** The setter method for this Customer's orders.
*/
public void setOrders(Set oOrders) {
orders = oOrders;
}
}
Hibernate Annotations
|
Hibernate, like all other object/relational mapping tools, requires metadata that governs the transformation of data from one representation to the other (and vice versa). As an option, you can now use JDK 5.0 annotations for object/relational mapping with Hibernate 3.2. You can use annotations in addition to or as a replacement of XML mapping metadata.
The Hibernate Annotations package includes:
- Standardized Java Persistence and EJB 3.0 (JSR 220) object/relational mapping annotations
- Hibernate-specific extension annotations
- Annotations for data integrity validation with the included Hibernate Validator API
- Domain object indexing/searching for Lucene via the included Hibernate Lucene framework
|
More detailed information can be found on the Hibernate website
.
Our Customer class now changes into the following annotated POJO:
@Entity
public class Customer implements Serializable {
@OneToMany
@JoinColumn(name="order_fk")
public Set<Order> getOrders() {
...
}
Hibernate with annotations has evolved into the JBoss implementation of EJB3 making it a great migration path into JEE5.
Java Persistence API (JPA)
The Java Persistence API (JPA) is the standard API for the management of persistence and object/relational mapping. It provides an object/relational mapping facility for application developers using a Java domain model to manage a relational database. The Java Persistence API is part of the Java EE platform.
| JPA can also be used in Java SE environments and rumors are spreading that JPA will be included in JSE7 for ORM support within the Java language. |
You can listen to several very interesting JPA talks at Parleys.com
, two JPA talks presented at SpringOne 2006 by the EJB3 spec. leads Mike Keith and Patrick Linskey and another by Rod Johnson and Costin Leau on how to use JPA with Spring.
Data Access Objects (DAO)
The Data Access Object (DAO) pattern was defined in the Core J2EE patterns
book by Deepak Alur, John Crupi and Dan Malks. Below you can see an extract of the different J2EE patterns explained within this book.
| Keep in mind that with the introduction of the Spring framework and JEE5 some of these patterns have been made obsolete (for example ServiceLocator) through the introduction of EJB3 and JPA or the implementation can be simplified by using dependency injection and annotations. |
DAO pattern
(in short) allows you to centralize all persistent logic and implement one or more persistent strategy.
| Avoid the introduction of 'pure' business logic within the persistence layer, this should be moved into the service layer. Of course persistence related logic can be moved into the DAO layer. |
To Stored Procedures, or Not ?
Depending on the skills available within your team you can consider to move persistence logic as stored procedures within your database. Many companies standardize on Oracle which is a the Ferrari of the databases, so make sure you don't only use the radio! Of course it helps if you've a DBA in your team.
The downside of using stored procedures is the difficulty to unit test, dbunit doesn't really help. If anybody out there knows how to do this then please add a comment to this page.
On the other hand the advantage of using stored procedures introduces very simple and small 'pass-through' DAO's because of course the persistent logic is now stored in the database.
Development teams without a DBA member will need to implement this persistent logic in the DAO resulting often in some bulky classes however the advantage from this approach is that it's all Java and unit testing this logic is not a problem.
Spring Persistence Templates
DAO implementations can be simplified using the Spring DAO Templating support for either Hibernate, JDBC, JDO, JPA and even TopLink.
Please avoid writing your own "JDBCUtil" kind of class, just use the related Spring template classes.
The above class diagram shows what is needed as a basic setup for such a DAO implementation.
I've seen projects where people add some more abstraction to this design by adding an additional AbstractDao class
and even an Dao interface allowing you to move shared DAO logic into that level.
Adding generics to this approach can really introduce some general purpose DAO's!
In addition introducing a PersistentObject interface and AbstractPersistentObject class allows you to collect some commonalities like the optimistic locking logic and some getters and setters for id, modification and creation date (if needed).
A simplistic code example could look like this :
public interface CustomerDao {
void persist(Customer customer);
boolean delete(Customer customer);
Customer get(long id);
}
| Please ignore the public modifier in the DAO interface as all methods are implicitly public when defined in an interface. |
public class CustomerDaoHibernateImpl extends HibernateDaoSupport implements CustomerDao {
public Customer get(long id) throws DataAccessException {
return this.getHibernateTemplate().find(
"from customer where id=?", id);
}
}
The only thing missing in the Spring example is the opportunity to move the JDBC/Hibernate specific parameters into a jdbc.properties and hibernate.properties file, like this :
...
<bean id="propertyConfigurer"
class="org.springframework.beans.factory.config.PropertyPlaceholderConfigurer">
<property name="locations">
<list>
<value>classpath:/jdbc.properties</value>
<value>classpath:/hibernate.properties</value>
</list>
</property>
</bean>
<bean id="dataSource"
class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="${db.driverClassName}" />
<property name="url" value="${db.url}" />
<property name="username" value="${db.username}" />
<property name="password" value="${db.password}" />
</bean>
...
With this setup you can move the hibernate and database specific data into a dedicated property file which now can easily be different on the development or staging machine.
An example jdbc property file:
db.driverClassName=oracle.jdbc.driver.OracleDriver
db.url=jdbc:oracle:thin:@xx.xx.xx.xx:1521:yyyyyy
db.username=xxxxxx
db.password=yyyyyy
db.schemaName=zzzzzz
db.dialect=org.hibernate.dialect.Oracle9Dialect
db.show_sql=true
And a possible hibernate properties file:
##################################################################
#
# Hibernate settings using Oracle dialect
#
##################################################################
hibernate.show_sql=true
# Needs to change to create if you want to delete some table
# Create-drop will drop tables after the sessionfactory is closed
hibernate.hbm2ddl.auto=update
#entry for enabling the cache
# hibernate.cache.provider_class=org.hibernate.cache.EhCacheProvider
hibernate.query.substitutions= true 1, false 0
| The Spring framework also supports the above mentioned design for Object Relational Mapping technologies like JPA, JDO and TopLink. If you want to develop your DAO's using JDBC then a JDBC Spring template is also available! |