Recommended: Sing it, brah! 5 fabulous songs for developers
JW's Top 5
Optimize with a SATA RAID Storage Solution
Range of capacities as low as $1250 per TB. Ideal if you currently rely on servers/disks/JBODs
Page 5 of 6
Even a perfect database abstraction is leaky in practice. Different databases behave differently and have specific locking and performance characteristics, in particular. An application might run and scale perfectly on one database but encounter frequent deadlocks with another product. No abstractions or design patterns can neutralize such variations. The only possible way to survive such a migration is to tweak the isolation levels, transactions, and database configuration. These issues can't be hidden behind a DAO interface, and it's likely that the DAO implementation would not even change. The DAO abstraction would be only useful if the actual JPA-QL or SQL statements change, which is a minor problem.
So neither the original definition nor a database-migration use case justifies the implementation of a dedicated DAO. So are DAOs dead? For standard use cases, yes. But you still need a DAO in most applications to adhere to the principles of DRY (don't repeat yourself) and separation of concerns. It is more than likely that an average application uses a set of common database operations over and over again. Without a dedicated DAO, the queries will be sprinkled through your business tier. Such duplication significantly decreases the application's maintainability. But the redundant code can be easily eliminated with a DAO that encapsulates the common data-access logic.
DAOs aren't dead, but they cannot be considered as a general best practice any more. They should be created in a bottom-up,
rather than a top-down, fashion. If you discover data-access code duplication in your service layer, just factor it out to
a dedicated DAO and reuse it. Otherwise it is just fine to delegate to an EntityManager from a service. The enforcement of an empty DAO layer is even more harmful, because it requires you to write dumb code for
even simple use cases. The more code is produced, the more time you must spend to write tests and to maintain it.
With JDK 1.5 and the advent of generics, it is possible to build and deploy a generic, convenient, and typesafe DAO once and reuse it from variety of services. Such a DAO should come with a business interface to encourage unit testing and mocking. Listing 4 shows an example of such an interface.
public interface CrudService {
public <T> T create(T t);
public <T> T find(Class<T> type,Object id);
public <T> T update(T t);
public void delete(Object t);
public List findWithNamedQuery(String queryName);
public List findWithNamedQuery(String queryName,int resultLimit);
public List findWithNamedQuery(String namedQueryName, Map<String,Object> parameters);
public List findWithNamedQuery(String namedQueryName, Map<String,Object> parameters,int resultLimit);
}
However, the business interface is optional in EJB 3.1. The DAO interface must be executed only in the context of an already
existing transaction, so it is @Local and comes with the MANDATORY transaction setting
Instead of polluting this POJI with a @Local annotation, you expose it by the session bean implementation instead. The bean implementation itself delegates to the EntityManager only in simple cases. You should increase the DAO's value and encapsulate reusable, project-specific queries in it. Listing
5 shows a generic DAO, realized as a service.