4

I'm currently working on the project where this discussion came and I wanted to ask others what do they think about this.

The DAO pattern is (according to wikipedia): "In computer software, a data access object (DAO) is an object that provides an abstract interface to some type of database or persistence mechanism, providing some specific operations without exposing details of the database.".

But, using ORM this is clearly an ORM (eg. Hibernate) job. It exactly provides an abstract interface to some (almost any) type of database.

Reviewing few last projects let's look on the DAO layer. First step is always generic hibernate dao with save(), findById(), findAll() methods. This is for me just proxying hibernate session methods.

A step further I see such interfaces like proposed here: Generic DAO pattern in Hibernate, what completely tightly bounds the DAO to hibernate way of doing persistence (merge, criteria query). This DAO wont be usable with other persistence mechanism than Hibernate.

So the final though is a question: for such common DAO design what new brings DAO pattern? If I want to switch database engine, I'm switching it on hibernate level. So, is this really any benefits currently from using DAO patterns in ORM applications?

Let's collect some experience:

  1. How many times have you seen the DAO class hierarchy tightly bound to Hibernate (or other ORM) and what do you think about benefits from that?
  2. In how many projects do you changed the persistence mechanism in the way that you got benefits from DAO layer (ie. you needed to implement other DAO layer because your job cannot be done on ORM level by switching db dialect)?
  3. In how many projects you just developed large DAO structure (interface+class for each domain object) and never used this really (ie. you never changed implementation of base DAO hierarchy)?
  4. What do you think, then, about applications without DAO layer, just using the abstraction provided by ORM sessions?

Please share with experience.

Community
  • 1
  • 1
Lukasz Frankowski
  • 2,955
  • 1
  • 31
  • 32

1 Answers1

2

IMHO, the DAO pattern, when using an ORM, is not really about the ability to switch the database engine. It's about

  • separating the responsibilities: business logic goes to the service layer, persistence goes to the DAO layer
  • being able to test the service layer by mocking the DAO layer
  • being able to test the persistence logic, because it's not buried inside the business logic

I usually prefer not to have a DAO per domain object, but rather a DAO per set of functional use-cases. Indeed, I've found that most of the queries, in a sufficiently complex application, are not linked to a specific domain object, but rather to a use-case or a set of use-cases. But YMMV, and combining both approaches is sometimes useful.

So, to answer your specific questions:

  1. nearly always. Using a DAO using Hibernate or JPA is not the same as using a DAO using plain JDBC, most of the time
  2. never. Usually, the choice of the database is done long before the project starts, and never changes.
  3. I tend to only develop a DAO when I need it, and not because a domain object exists. But having a "generic DAO" base class is sometimes handy
  4. I think they're harder to test, are often not well-structured, and end up reimplementing the same queries/loadings over and over again because those are not isolated in a reusable DAO
JB Nizet
  • 678,734
  • 91
  • 1,224
  • 1,255
  • Thanks for replying. Then, I have another questions: 1. Can't you mock and make tests on service layer, which directly use Session abstraction in the default implementation? 2. What exactly do you mean by "DAO per usecase"? This is new for me, since I'm using this pattern too, but on service layer I know that the another problem in this approach is to collect somewhere methods accessing data - complex, repeatable queries. This may be default be done on DAO layer, but usually this is the repeated on service layer, which are just proxies to these DAO (from what I don't see much benefits). – Lukasz Frankowski Aug 09 '11 at 11:23
  • 1. No, because session methods are too coarse-grained, and not sufficiently specific. It's easier to mock (and verify) dao.findFoosByField(String) than session.createQuery(String) followed by query.setMaxResults() followed by query.list(). 2. For example, I might have a single DAO for authorization management, which would handle the persistence of users, roles, profiles, rather than one DAO for user, one other for role and one other for profile. – JB Nizet Aug 09 '11 at 11:36
  • OK, I understand. I use rather DB population for testing than mocking, so the mocking DAO doesn't really help me. Another stuff with DAO I see here is the problem with limiting/ordering. In results there are need plenty of methods with these params required, and this all is already exposed a layer a step down with very handy interface. I'm really close to turn to different solution. – Lukasz Frankowski Aug 09 '11 at 12:46
  • The you're not really unit testing, and your tests are much longer to tun than necessary. Mocking helps testing business logic without having to maintain a dataset, makes tests run very fast, and really helps to test corner-cases. – JB Nizet Aug 09 '11 at 13:02
  • 1
    I know this approach a little but it's hard to believe in this to me. The thing my apps do usually is to get data from db, processes them and put something again to db. For me then, this is much closer to real situation, test this on db (and by the way test things related to persistence, like relations etc.). Sorry for my non-conformism, I just have recently two medium size projects on my desk written using completely different approach and I see there, that the classis app has 100-150% code more (and work time required), completely without any reason - this made me to think about this;) – Lukasz Frankowski Aug 09 '11 at 13:27
  • More code does not necessarily means more work time required. i.e. some code generators can be used. – Pau Aug 11 '11 at 15:20