Data Access Object (English)

Z FI WIKI
Přejít na: navigace, hledání
Tato stránka je dostupná také v češtině: Data Access Object

Description

Imagine a situation where your successful company got a contract to develop an application for two different clients. The specification is roughly the same despite some minor differences. This plot has a twist though. Both clients use SQL databases but one decided to go for a proprietary one and the other chose an open source alternative. This implies that your application will have to have persistence layer implemented in at least two different ways. Naturally, many more implementations may be needed as new clients arise. Your best choice to solve this portability problem in Java EE would be using one of core J2EE patterns - Data Access Object.

Data Access Object(henceforth only DAO) is used to abstract and encapsulate all access to the data source. DAO manages the connection with the data source to obtain and store data(alur 2003). In other words, DAO simply introduces an interface between the data source and the data consumers, isolates data obtaining logic into one layer and by doing this segregates data persistence from business logic.

Benefits

In conclusion the usage of the DAO pattern (alur 2003):

  • Enables transparency
  • Enables easier migration
  • Reduces code complexity in business objects
  • Centralizes all data access into a separate layer
  • Adds extra layer

DAO pattern usage requires class hierarchy design(such as one provided by Spring or EJB).

Príklad DAO triedy

Following code is an example of class designed as DAO. This class represents simple roster for some team. In the lower half, JPQL is used for data extraction from relational database.

 
 
/**
 * This is an example of Data Access Object
 *
 * @author Andrej Makovicky
 */
@Repository
public class RosterDAOImpl implements RosterDAO {
    
    @PersistenceContext 
    private EntityManager em;
    
    
    @Override
    @Transactional
    public void addRoster(Roster roster) {
        
        if (roster == null) {
            throw new IllegalArgumentException("Roster is null.");
        } 
        
        if (roster.getId() != null) {
            throw new IllegalArgumentException("Roster has already ID.");
        }
        
        if (roster.getTeam() == null) {
            throw new IllegalArgumentException("Roster has not got assigned team.");
        }
        
        if (roster.getCategory() == null) {
            throw new IllegalArgumentException("Roster has not got assigned category.");
        }
        
        em.persist(roster);
    }
 
    @Override
    @Transactional
    public void removeRoster(Roster roster) {
        
        if (roster == null) {
            throw new IllegalArgumentException("Roster is null.");
        } 
        
        if (roster.getId() == null) {
            throw new IllegalArgumentException("Roster has no ID.");
        }
        
        em.remove(em.merge(roster));
        
    }
 
    @Override
    @Transactional
    public void updateRoster(Roster roster) {
        if (roster == null) {
            throw new IllegalArgumentException("Roster is null.");
        }
        
        if (roster.getId() == null) {
            throw new IllegalArgumentException("ID of roster is null.");
        }
        
        if (roster.getTeam() == null) {
            throw new IllegalArgumentException("Roster has no assigned team.");
        }
        
        if (roster.getCategory() == null) {
            throw new IllegalArgumentException("Roster has no assigned category");
        }
        em.merge(roster);
    }
    
    @Override
    @Transactional
    public List<Roster> findAllRosters() {
        Query query = em.createQuery("SELECT r FROM Roster r");
        List<Roster> list = query.getResultList();
        return list;
    }
    
    @Override
    @Transactional
    public List<Roster> findAllRostersForTeam(Team team) {
        Query query = em.createQuery("SELECT r FROM Roster r WHERE team = :team");
        query.setParameter("team", team);
        List<Roster> list = query.getResultList();
        return list;
    }
    
    @Override
    @Transactional
    public Roster findById(Long id) {
        
        if (id == null) {
            throw new IllegalArgumentException("Id is null.");
        }
        Roster roster = em.find(Roster.class, id);
        return roster;
    }
    
}
 

For an extensive range of examples and a deeper insight into this problematic, I recommend either great book on J2EE Core Patterns (alur 2003) or an online documentation: http://www.oracle.com/technetwork/java/dataaccessobject-138824.html.

References

  • D. Alur, J. Crupi, and D. Malks. Core J2EE Patterns: Best Practicies and Design. Core Design Series. Prentice Hall Ptr, 2003.