Data Access Layer Architecture using Spring and JPA

Submitted by David on Mon, 02/01/2010 - 10:05

High Level Data Access Layer Java Architecture

The java application architecture for this Data layer will be based on the Domain Driven Design. Domain ojbects can be mapped to Database tables via annotations. These domain objects can be queried via JPA in the DAO layer and passed up through the service layer and passed to the presentation layer.

The DAO layer will have the JPA entity manager injected via the persistence unit name. This layer will handle the JPQL (java persistence query language) when querying the database. It will also contain the java code for utilizing entity management built in functions such as find, persist, update, merge, and delete.

The Service layer will handle the Transaction management. This can be done by utilizing Java annotations. This feature rich solutions allows for annotating a single method as a transaction. This will begin the transaction when the method is called and will commit when the transaction when the method has been completed. The service layer simply will be using a specific DAO that can be injected

An example of setting up the XML configuration for Webflow and JPA can be seen in this post. Spring Configuration for JSF/JPA/Webflow Combination

A visual diagram/description that shows what this article is describing can be seen below. This is a detailed image of the Data Access Layer that shows the separation between service layer and DAO (data access object) layer. Note that the domain object is passed from the DAO layer to the presentation layer.

Java Annotated Domain Objects


@Entity(name="Employee")
@Table(name = "EMPLOYEE_DB_TABLE")
public class Employee {

@Id
@Column(name="ID")
private Long Id;

@Column(name="LAST_NAME")
private String lastName;

@Column(name="FIRST_NAME")
private String firstName;
...
}

Java DAO Layer with JPA Entity Manager

This is an example of a DAO for an Employee domain object. It uses the Spring injected EntityManager to

@Repository("employeeDAO")
public class EmployeeDAOImpl implements EmployeeDAO {
private EntityManager entityManager;

@PersistenceContext(unitName = "pUnit1")
public void setEntityManger(EntityManager entityManager) {
this.entityManager = entityManager;
}

public Employee find(Long id) {
return (Employee) entityManager.find(Employee.class, id);
}

@SuppressWarnings("unchecked")
public List loadAll() {
return entityManager.createQuery("select e from Employee e")
.getResultList();
}

public void delete(Employee employee) {
Employee entityAttached = entityManager.merge(employee);
entityManager.remove(entityAttached);
}

public void persist(Employee employee) {
entityManager.persist(employee);
}

@SuppressWarnings("unchecked")
public List findByLastName(String lastName) {
try {
Query query = entityManager.createQuery("select e from "
+ "Employee e where e.lastName = ?1 ");
query.setParameter(1, lastName);
List l = (List) query.getResultList();
return l;
} catch (NoResultException n) {}
return null;
}
}

Java Data Service Layer with Transaction Management

The Service Layer handles the transaction management. This example uses annotations get that done. The service layer has the DAO object injected and makes calls while handling transactions.


@Service("employeeService")
public class EmployeeServiceImpl implements EmployeeService {

@Autowired
@Qualifier("employeeDAO")
EmployeeDAO employeeDAO;

@Transactional(value="tx1", readOnly=true)
public List loadAll() {
return employeeDAO.loadAll();
}

@Transactional(value="tx1", readOnly=true)
public Employee find(Long id) {
return employeeDAO.find(id);
}

@Transactional(value="tx1", readOnly=false)
public void delete(Employee employee) {
employeeDAO.delete(employee);
}

@Transactional(value="tx1", readOnly=true)
public List findByLastName(String lastName) {
return employeeDAO.findByLastName(lastName);
}

@Transactional(value="tx1", readOnly=false)
public void save(Employee employee) {
employeeDAO.persist(employee);
}
}

The 'Transactional' annotation value corresponds to the Qualifier property in the Spring configuration where the Transaction Manager is defined.

Using the Service objects

The service object annotated by @Service("employeeService") can be used throughout the application. Based on the Domain Driven design model, the service layer can be utilized by the presentation layer. Just like any other Spring bean, the service can be injected into any Java class. For a JSF view, the employeeService is exposed to the view layer directly and can be refereced in JSF. Below is an example if referencing the service object from a JSF dataTable element.

Employee First Name
#{e.firstName}

Employee Last Name
#{e.lastName}