Home > Java > Do we really need the DAO?

Do we really need the DAO?

This may seem like a stupid question, especially after years of carefully creating them. Yet these thoughts about DAO arose in my mind when I watched Adam Bien’s Real World JavaEE rerun on Parley’s.

In his talk, Adam says he doesn’t use DAOs anymore – even though he has one ready so as to please architects (them again). My first reaction was utter rejection: layered architecture is at the root of decoupling and decoupling is a requirement for an evolutive design. Then, I digested the information and thought, why not?

Let’s have a look at the definition of the DAO design pattern from Oracle:

Use a Data Access Object (DAO) to abstract and encapsulate all access to the data source. The DAO manages the connection with the data source to obtain and store data.

Core J2EE Patterns – Data Access Object

Back in the old days, either with plain JDBC or EJB, having DAO was really about decoupling. Nowadays and when you think about that, isn’t it what JPA’s EntityManager is all about? In effect, most JPA DAO just delegate their base methods to the EntityManager.

public void merge(Person person) {
    em.merge(person);
}

So, for basic CRUD operations, the point seems a valid one, doesn’t it? That would be a fool’s conclusion, since the above snippet doesn’t take into account most cases. What if a Person has an Address (or more than one)? In web applications, we don’t have the whole object graph, only the Person to be merged, so we wouldn’t merge the entity but load it by it’s primary key and update fields that were likely changed in the GUI layer. The above snippet should probably look like the following:

public Person merge(Person person) {
    Person original = em.find(Person.class, person.getId());
    original.setFirstName(person.getFirstName());
    original.setLastName(person.getLastName());
    em.flush();
    return original;
}

But what about queries? Picture the following:

public class PersonService {

    public List<Person> findByFirstNameAndLastName(String firstName, String lastName) {

        CriteriaBuilder builder = em.getCriteriaBuilder();

        CriteriaQuery<Person> select = builder.createQuery(Person.class);

        Root<Person> fromPerson = select.from(Person.class);

        Predicate equalsFirstName = builder.equal(fromPerson.get(Person_.firstName), firstName);

        Predicate equalsLastName = builder.equal(fromPerson.get(Person_.lastName), lastName);

        select.where(builder.and(equalsFirstName, equalsLastName));

        return em.createQuery(select).getResultList();
    }
}

The findByFirstNameAndLastName() method clearly doesn’t use any business DSL but plain query DSL. In this case, and whatever the query strategy used (JPA-QL or Criteria), I don’t think it would be wise to use such code directly in the business layer and the DAO still has uses.

Both those examples lead me to think DAO are still needed in the current state of things. Anyway, asking these kind of questions are of great importance since patterns tend to stay even though technology improvements make them obsolete.

email
Send to Kindle
Categories: Java Tags:
  1. Leif
    December 23rd, 2012 at 20:29 | #1

    This topic has been on my mind lately too.

    12 months ago ORM’s were a new topic to me. We scrapped all our brittle JDBC code and annotated everything with Hibernate. Life was bliss. We had a DatabaseService layer to access our Hibernate entities. It was simple, it made sense.

    e.g. DatabaseService.java -> Person.java

    Shortly after we had a developer familiar with DAO’s join our project and now we have a layer of DAO’s.

    e.g. DatabaseService.java -> PersonDAO.java -> Person.java

    The prospect doesn’t really make sense to me. It moved all these simple Hibernate method calls from DatabaseService into DAO’s. It feels like DAO’s for the sake of DAO’s.

  2. me
    December 24th, 2012 at 13:53 | #2

    Do you know the Spring Data JPA project?

    It simplifies the implementation of the data access layer in many ways. For example, you can omit the implementation of your findByFirstNameAndLastName method completely. Such query methods are handled automagically.

    The reference documentation is very good:

    http://www.springsource.org/spring-data/jpa

    In the reference documentation of Spring Roo is a section titled “Goodbye DAOs”:

    http://static.springsource.org/spring-roo/reference/html/architecture.html#architecture-dao

  3. Oliver Gierke
    December 24th, 2012 at 19:53 | #3

    I actually discussed this topic quite a while ago already [0]. A core responsibility of a DAO or repository is that it has to encapsulate persitence technology specific aspects to free the rest of the code base from exactly those. Arguing that JPA removes the need for such an abstraction is fundamentally flawed in many ways. I’ve never met someone seriously suggesting mocking the EntityManager API who actually has tried doing so. This approach works fine for demoing mocking merge(…) or persist(…) but definitely gets out of hand if comes to query execution or even using the Criteria API. It’s much easier to mock a single userDao.myComplexQueryMethod(…) than a dozen calls to the EntityManager API.

    A second, architecturally crucial aspect of a DAO is that it defines context boundaries by being implemented for aggregate roots only. A JPA EntityManager is a low level, general-purpose persistence API, not too different from JDBC – from an architectural point of view at least. In a non-trivial application you’ll definitely want to restrict what parts of the system can actually use a UserRepository to create new users. If you use repositories, you can define access rules using SonarJ or the like. If you allow working with JPA directly, this kind of governance becomes much harder.

    Generally I think that the decision which code goes where is not one that should be made based on raw technical aspects. For a real world application aspects like maintability, testability and understandability are crucial. Yes, you write less persistence related code if you use JPA over JDBC. Nevertheless, using this fact as argument to simply inline data access code into your business logic is simply stupid, might work for 60 minute demos and even might survive a short consulting sprint. But it deeply subverts any long time maintainability strategy.

    A final word on Spring Data JPA. The project aims to reduce the amount of boilerplate needed to be written to implement a data access layer. It does so by actually centering the entire programming mode around a repository interface. So it acknowledges the need for a separation of data access code and effectively embraces it.

    [0] http://www.olivergierke.de/2009/01/se-radio-episode-121-or-mappers

  4. Marcus Kraßmann
    December 27th, 2012 at 23:21 | #4

    As far as I understood Adam in some of his JUGHH sessions, he uses “service” classes in a similar way how I personally use some DAOs, while my “services” would be “service facades” in his language. And in his former live examples, he used (sometimes IDE-generated) NamedQueries to access entities (IIRC). With those, you can use an EntityManager without the need to create a separate DAO. Also unit testing is almost perfectly possible as long as you just need to mock some relatively simple method calls. But when you start using more complex queries, especially when using the Criteria API or when having a lot of parameters to set, I definitely prefer to to encapsulate these very technical aspects into separate DAO methods. This way, I just need to mock exactly one method call instead of many ones.

    At some time, I found the Hades project (god bless the german “Java Magazin” and Ollis article) which is now Spring Data JPA. I must admit that I effectively include it in really every new Java project that needs to access a database. The query generation features are for me a very convenient, readable way to get rid of lots of “boilerplate entity fetching code”. For sure it is not a must-have library, but it helps to reduce of custom JPA code to the necessary minimum. Maybe Adam would also use it if it would not belong to Spring Source ;-))

    So I totally agree that DAOs still belong to the good patterns. They help me to mock out database aspects in unit tests. But especially for simpler queries, I still prefer simple query generation by DAO method name above Criteria queries. Although Criteria queries may be more refactoring safe, I don’t like their verbosity and complexity even for simple queries. A Spring Data JPA DAO method together with a simple unit test is easier to write and also refactoring safe (at least the test won’t pass).

  1. No trackbacks yet.