Help

One of the things in Hibernate in Action that needs serious improvement is the section about data access objects, the good old DAO pattern.

Things gone wrong

Some of the mistakes I've made in the first edition:

I assumed that DAO is not only a well known pattern, but that most people already had experience how to write /state-oriented/ data access object interfaces. It turns out that most developers are very familiar with /statement-oriented/ DAOs, like you would implement with plain JDBC or iBatis (or the new stateless Hibernate Session in Hibernate 3.1), but never thought about persistence services with active object state management before - and how to design an application data access interface for such a service.

All examples had internal exception handling. Now, in a real application I'd just take the Hibernate 2.x source code, replace HibernateException extends Exception with HibernateException extends RuntimeException and leave it to my controlling code, not the data access objects, to convert and handle exceptions (including transaction rollback).

But, in the book, I was trying to avoid this issue, something we should actually have resolved in Hibernate 2.x a long time ago. We finally switched to unchecked exceptions in Hibernate 3.x but I still see many DAO snippets that include some kind of exception handling (or even worse, an exception handling /framework/) for unchecked exceptions.

Finally, lazy transaction demarcation, that is, starting a transaction if the current thread doesn't already have one, was only shown as part of the DAO constructor. There are many other ways to do this. One would be the DAO factory, which I also skipped in the book, (wrongly) assuming that everybody knows how to write a factory.

Some other common mistakes I've seen in the past (even in recent other Hibernate books) and you should avoid when writing your DAOs:

Excessive exception handling and wrapping. You should never have to wrap and re-throw an unchecked exception in a DAO method, certainly not for logging, or worse to swallow the exception. Avoid, change, or wrap persistence services that only throw checked exceptions. The only exception states of interest, in higher level code, are retry the unit of work (e.g. database connection failed, lock couldn't be aquired, etc.) or don't retry the unit of work (constraint violation, SQL error, etc.). Everything else, like exceptions typed to the exact SQL error, are sugar on top - at most good for better looking error message screens. You can't use database exceptions for validation or any other regular data processing. Don't let yourself be fooled by the elaborate exception hierarchies in Hibernate and other frameworks.

Ignorance of object state management. If you have a full ORM solution like Hibernate, you get automatic object state management. If a property value of a business object instance is modified you don't have to call saveThisObject() on a DAO, automatic dirty checking is provided inside a transaction. Or, if you write your DAO with state management in mind, understand the state transitions to avoid unnecessary code: session.update(o) does not need to be called before session.delete(o), for example.

Session per operation anti-pattern. Never should you use a new Hibernate Session for each DAO operation. A unit of work has a larger scope and your Hibernate application will perform horrible with this anti-pattern. This is very easy to avoid, just setthe DAO's Session when it is constructed or look it up from a thread local. In fact, the scope of the Session often seems to be handled ad-hoc and on a this is better looking code basis, when it should actually be a conscious design decision.

So, in the second edition I plan to include more than just 4 pages about the DAO pattern and write more about state/statement-oriented APIs, exception handling, how to best deal with lazy transactions, how to add factories into the mix, and so on. I'll even include DAOs written as stateless EJB 3.0 session beans.

New DAO pattern for JDK 5.0

I wanted to actually defer updating the DAO section until I would work on that chapter in the book. However, some guys made proposals for /generic/ DAOs on the CaveatEmptor forum and I realized it really is time to put some of the new JDK 5.0 features to good use (besides annotations, of course). If you are still using JDK 1.4 primarily you might want to stop reading now... but I strongly encourage you to read the Hibernate in Action DAO examples (and any other examples, for that matter) with the caveats mentioned above in mind.

If you are using JDK 5.0, get the CaveatEmptor alpha2 release now. Let's walk through some of the DAO source code.

This time I based the DAO example on interfaces. Tools like Hibernate already provide database portability, so persistence layer portability shouldn't be a driving motivation for interfaces. However, DAO interfaces make sense in more complex applications, when several persistence services are encapsulate in one persistence layer, and they deserve more than a note (which was all I did in HiA first edition).

I use one interface per persistent entity, with a super interface for common CRUD functionality:

public interface GenericDAO<T, ID extends Serializable> {

    T findById(ID id, boolean lock);

    List<T> findAll();

    List<T> findByExample(T exampleInstance);

    T makePersistent(T entity);

    void makeTransient(T entity);
}

You can already see that this is going to be a pattern for a state-oriented data access API, with methods such as makePersistent() and makeTransient(). Furthermore, to implement a DAO you have to provide a type and an identifier argument. As for most ORM solutions, identifier types have to be serializable.

The DAO interface for a particular entity extends the generic interface and provides the type arguments:

public interface ItemDAO extends GenericDAO<Item, Long> {

    public static final String QUERY_MAXBID = "ItemDAO.QUERY_MAXBID";
    public static final String QUERY_MINBID = "ItemDAO.QUERY_MINBID";

    Bid getMaxBid(Long itemId);
    Bid getMinBid(Long itemId);

}

We basically separate generic CRUD operations and actual business-related data access operations from each other. (Ignore the named query constants for now, they are convenient if you use annotations.) However, even if only CRUD operations are needed for a particular entity, you should still write an interface for it, even it it is going to be empty. It is important to use a concrete DAO in your controller code, otherwise you will face some refactoring once you have to introduce specific data access operations for this entity.

An implementation of the interfaces could be done with any state-management capable persistence service. First, the generic CRUD implementation with Hibernate:

public class GenericHibernateDAO<T, ID extends Serializable> implements GenericDAO<T, ID> {

    private Class<T> persistentClass;
    private Session session;

    public GenericHibernateDAO(Class<T> persistentClass, Session session) {
        this.persistentClass = persistentClass;
        this.session = session;
    }

    protected Session getSession() {
        return session;
    }

    public Class<T> getPersistentClass() {
        return persistentClass;
    }

    public T findById(ID id, boolean lock) {
        T entity;
        if (lock)
            entity = (T) getSession().load(getPersistentClass(), id, LockMode.UPGRADE);
        else
            entity = (T) getSession().load(getPersistentClass(), id);

        return entity;
    }

    @SuppressWarnings("unchecked")
    public List<T> findAll() {
        return findByCriteria();
    }

    @SuppressWarnings("unchecked")
    public List<T> findByExample(T exampleInstance) {
        return findByCriteria( Example.create(exampleInstance) );
    }

    @SuppressWarnings("unchecked")
    public T makePersistent(T entity) {
        getSession().saveOrUpdate(entity);
        return entity;
    }

    public void makeTransient(T entity) {
        getSession().delete(entity);
    }

    /**
     * Use this inside subclasses as a convenience method.
     */
    @SuppressWarnings("unchecked")
    protected List<T> findByCriteria(Criterion... criterion) {
        Criteria crit = getSession().createCriteria(getPersistentClass());
        for (Criterion c : criterion) {
            crit.add(c);
        }
        return crit.list();
   }

}

There are some interesting things in this implementation. First, it clearly needs a Session to work, provided to the constructor. How you set the Session, and what scope this Session has is of no concern to the actual DAO implementation. What follows are the implementations of the generic CRUD operations, quite straightforward. The last method is quite nice, using another JDK 5.0 feature, /varargs/. It helps us to build Criteria queries in concrete entity DAOs. This is an example of a concrete DAO that extends the generic DAO implementation for Hibernate:

public class ItemDAOHibernate
        extends     GenericHibernateDAO<Item, Long>
        implements  ItemDAO {

    public ItemDAOHibernate(Session session) {
        super(Item.class, session);
    }

    public Bid getMaxBid(Long itemId) {
        Query q = getSession().getNamedQuery(ItemDAO.QUERY_MAXBID);
        q.setParameter("itemid", itemId);
        return (Bid) q.uniqueResult();
    }

    public Bid getMinBid(Long itemId) {
        Query q = getSession().getNamedQuery(ItemDAO.QUERY_MINBID);
        q.setParameter("itemid", itemId);
        return (Bid) q.uniqueResult();
    }

}

Another example which uses the findByCriteria() method of the superclass with variable arguments:

public class CategoryDAOHibernate
        extends     GenericHibernateDAO<Category, Long>
        implements  CategoryDAO {

    public CategoryDAOHibernate(Session session) {
        super(Category.class, session);
    }

    public Collection<Category> findAll(boolean onlyRootCategories) {
        if (onlyRootCategories)
            return findByCriteria( Expression.isNull("parent") );
        else
            return findAll();
    }
}

We bring it all together in a DAO factory, which not only sets the Session when a DAO is constructed, but can also take care of lazy transaction starting, and contains inline classes to implement CRUD-only DAOs with no business-related operations:

public class HibernateDAOFactory extends DAOFactory {

    public ItemDAO getItemDAO() {
        return new ItemDAOHibernate(getCurrentSession());
    }

    public CategoryDAO getCategoryDAO() {
        return new CategoryDAOHibernate(getCurrentSession());
    }

    public UserDAO getUserDAO() {
        // Inline implementation, constructor only
        class UserDAOHibernate
                extends GenericHibernateDAO<User, Long>
                implements UserDAO {

            public UserDAOHibernate(Session session) {
                super(User.class, session);
            }

        }

        return new UserDAOHibernate(getCurrentSession());
    }

    protected Session getCurrentSession() {
        // Get a Session and begin a database transaction. If the current
        // thread/EJB already has an open Session and an ongoing Transaction,
        // this is a no-op and only returns a reference to the current Session.
        HibernateUtil.beginTransaction();
        return HibernateUtil.getCurrentSession();
    }

}

This concrete factory for Hibernate DAOs extends the abstract factory, which is the interface we'll use in application code:

public abstract class DAOFactory {

    public static final DAOFactory EJB3_PERSISTENCE =
            new org.hibernate.ce.auction.dao.ejb3.Ejb3DAOFactory();

    public static final DAOFactory HIBERNATE =
            new org.hibernate.ce.auction.dao.hibernate.HibernateDAOFactory();

    public static final DAOFactory DEFAULT = HIBERNATE;

    // Add your DAO interfaces here
    public abstract ItemDAO getItemDAO();
    public abstract CategoryDAO getCategoryDAO();
    public abstract CommentDAO getCommentDAO();
    public abstract UserDAO getUserDAO();
    public abstract CategorizedItemDAO getCategorizedItemDAO();
}

Of course, the DEFAULT could be externalized to some configuration setting if your application needs to switch persistence layers for each deployment. Note that this factory example is suitable for persistence layers which are primarily implemented with a single persistence service, such as Hibernate or EJB 3.0 persistence. If you have to mix persistence APIs, for example, Hibernate and plain JDBC, the pattern changes slightly. I'll write more about it in the book - keep in mind that you can also call session.connection() /inside/ a Hibernate-specific DAO, or use one of the many bulk operation/SQL support options in Hibernate 3.1 to avoid plain JDBC.

Finally, this is how data access now looks like in controller/command handler code:

ItemDAO itemDAO = DAOFactory.DEFAULT.getItemDAO();
UserDAO userDAO = DAOFactory.DEFAULT.getUserDAO();

public void execute() {

    Bid currentMaxBid = itemDAO.getMaxBid(itemId);
    Bid currentMinBid = itemDAO.getMinBid(itemId);

    Item item = itemDAO.findById(itemId, true);

    newBid = item.placeBid(userDAO.findById(userId, false),
                            bidAmount,
                            currentMaxBid,
                            currentMinBid);
}

Two links you might find useful: ThreadLocal Session and Open Session in View

I also plan to write a section about /integration testing/ of DAOs. What do you think about this pattern? Did I miss anything and what else do you want covered in the book?

P.S. Credit has to be given to Eric Burke, who first posted the basics for this pattern on his blog. Unfortunately, not even the Google cache is available anymore.

27 comments:
 
12. Sep 2005, 09:34 CET | Link
David Carter | david(AT)carter.net
Christian - great article! I'm looking forward to the next edition of HIA. One question - is the DAO the right place to deal with query caching? If so, how. If not, where should it be addressed in the architecture? Thanks!
 
12. Sep 2005, 17:31 CET | Link
Christian
If you think about "query caching" as in Hibernate, this is transparent, except that you have to enable it for a particular query with setCacheable(true). This call would be in a DAO method.

 
15. Sep 2005, 12:10 CET | Link
From HibernateDAOFactory

    protected Session getCurrentSession() {
        // Get a Session and begin a database transaction. If the current
        // thread/EJB already has an open Session and an ongoing Transaction,
        // this is a no-op and only returns a reference to the current Session.
        HibernateUtil.beginTransaction();
        return HibernateUtil.getCurrentSession();
    }

call HibernateUtil.beginTransaction();
creates a transaction even in cases when
it is not required. Ex: DAO is used only with finder
methods (i.e. does SQL 'select' which is not a transaction).

This will create unnesessary locking in a database and could seriously impact
performance of certain class of applications.

I don't think transaction management belongs
to DAO or its factory. Or for 'lazy' transaction
creation it should be done only at the DAO
methods which modify database such as
update, delete, create, but not finder methods.

Might be you need something like getSessionWithTransaction() method.


  
 
15. Sep 2005, 23:04 CET | Link
I am interrested in DAO pattern ... But more in Hibernate integration process in large application dev.

I am actually looking for how to use Hibernate as a replacement of OFBiz EE. My quest is mainly how to organize entities development using Hibernate tools and runtime in Eclipse without so much overhead. An optmized entities dev lifecycle is central here ... Choosing only one of: annotations in entities class or XML in mapping files or reversing from Database sources. I think for productivity, most users are first interrested by the best optimal dev process with easy of maintenance and extension of large applications.
  
 
15. Sep 2005, 23:05 CET | Link
Christian
You always need transaction boundaries, no matter if you read or write. You have been confused by the auto-commit mode.

 
15. Sep 2005, 23:05 CET | Link
Christian
Claude, you are looking for http://forum.hibernate.org/

 
16. Sep 2005, 02:25 CET | Link
>You always need transaction boundaries, no matter if you read or write.

What if my application is just for browsing a database and it never modifies entities?
Why would it need transaction boundaries defined? Why would DAO factory always
create/join a transaction?

If I create DAO from a EJB business method under CMT with Never
it should not create a transaction.

>You have been confused by the auto-commit mode.

No.



 
16. Sep 2005, 14:17 CET | Link
Christian
Explain why you think that many small transactions in auto-commit mode are going to be better or faster for "reading data" than one clearly defined unit of work?

 
17. Sep 2005, 05:43 CET | Link
Anonymous Guest
>What if my application is just for browsing a database and it never modifies entities?
Why would it need transaction boundaries defined?

Reading data is unit of work, it should avoid "durty reads" etc. If such reading takes 10 minutes, for instance, it should be "atomic" read in some point in time, with consistent data; data could be modified by another application during this 10-minutes "unit of work".

"Transaction" is not same as "Lock".

For instance, Oracle uses some kind of log files behind the scenes, and application can read consistent data while another application modifies it; with specific exceptions defined like "Old Data" etc.

Am I right guys?

 
17. Sep 2005, 23:03 CET | Link
Christian
I'll write a blog entry about transaction basics in a few weeks, I guess...

 
17. Sep 2005, 23:05 CET | Link
Christian
"In my understanding a Session is a short-living single-threaded cache, isn't it dangerous to use on Session for all the DAOs?"

This is exactly the opposite of what I'm saying in the blog entry and what can be found in any (good) Hibernate documentation.

 
18. Sep 2005, 02:13 CET | Link
Christian
Oh, now I got it, you haven't read http://hibernate.org/42.html

 
19. Sep 2005, 18:54 CET | Link
Yes, that was the missing link. So you open a session for each thread. Slowly getting there. Thanks a million,
Dora
 
06. Oct 2005, 07:05 CET | Link
I'm sorry if this is a newbie question, but...
In your GenericHibernateDAO implementation for findById you use session().load() as apposed to session.get(). It seems that the client of the DAO method should easily be able to know if the object was found or not. As you know, get returns either the persisted instance, or null vs. the load which returns either a proxy or an instance. What are the advantages of load vs. get in this case, and if load is better, what's the best way to identify if the object was found or not?
 
10. Oct 2005, 16:52 CET | Link
Rafal Piotrowski | rafal.SPAM(AT)piotrowscy.com
I mainly developing RCP applications, there is very little written on what is the best practice to use Hibernate in such scenarios. I like the fact of using lazy loading, but since the session is managed by Spring Hibernate session manager (yes, I use spring) I have no option other then turn off lazy loading, which basicly makes the use of ORM Hibernate technology useless (I don't want to load whole DB into my client's memory). Therefore my question is: Can you or some other Hibernate GURU write some article describing what is the BEST way to use Hibernate in RCP or just simply saying that IT IS NOT a technology for RCP?
Many thanks,
rp
 
13. Oct 2005, 01:03 CET | Link
Christian
Some updates of this pattern have been made, check the Wiki: http://www.hibernate.org/328.html
 
18. Oct 2005, 22:29 CET | Link
Michael Slattery
I wrote a blog with a similar idea a month earlier and got some negative feedback. However, I still think it's a great idea (to use generic base code for DAOs).

http://www.jroller.com/page/MikeSlattery?entry=a_single_dao_for_less

 
26. Oct 2005, 01:49 CET | Link
Joe
Nice article!

>What do you think about this pattern?
> Did I miss anything and what else do you
> want covered in the book?

I agree with Rafal Piotrowski's comment. I would like it if the new edition of the HiA book could have a section on using Hibernate in rich client applications (both 2-tier and 3-tier). The Open Session in View pattern is great for web apps but it's not really suitable for rich client apps as pointed out in http://www.hibernate.org/43.html#A4.

In my rich client app, one pattern I've been using with some good results is to use your notion of "report queries" for efficiently returning a list of "summarized" objects to the UI. These summarized objects present a small view of only the essential properties of a much larger object (and it's graph of child objects). Then, if the user wants to zoom in on the full object to see more details or to edit it, they can execute a session.load() for the object, passing the id contained in the summary object.

As you suggested on page 276 of HiA, I'm avoiding the temptation to rewrite ALL of my read-only transactions to use report queries. However, I find they are very useful for "aggregate" objects that include many child objects. They allow me to avoid loading a huge object graph unnecessarily.

Anyway, can you please talk about rich client best practices in your new book?

 
01. Nov 2005, 18:56 CET | Link
Hi Christian,

Im using the generic DAO pattern; I have one GenericHibernateDAO and one GenericMockDAO. I generate the implementations with annotations. This way I annotate the beans, and create the DAOs on the fly.

The generic mock was initially very simple; you could put in an object and retrieve it later. As we want the Mock and the Hibernate DAO to work in the same fashion, I started to implement associations and cascading in the mock.

My fear is that I gonna end up in a very complicated GenericMockDAO class if I want to support more of the Hibernate mapping fetures. What approach do you recommend for implementing a mock DAO layer?

Thank you a lot in advance,
Dora

PS: sorry if there's a different topic for mocks already, I couldn't find it.


 
04. Nov 2005, 04:01 CET | Link
bostonjava
Hi Christian:

I am trying out the generic DAO pattern. After running my applicatin for a while I get the following warnings

WARN - afterTransactionCompletion() was never called
WARN - unclosed connection, forgot to call close() on your session?

Looking back at the code, in HibernateDAOFactory, I see that getCurrentSession() method starts a transaction and returns the current session. These are never closed anywhere. What am I missing?

Thanks
 
09. Nov 2005, 22:28 CET | Link
rihards
How and when do you reset ThreadLocal Session? If I load Person with id 1 once and then When I do it again - wont it be returned from Session cache? Also working with same Session for very long time was making all operations with this Session to become extremly slow after some period of time... I guess because waste amount of dehidrated entity states it was holding...
 
11. Dec 2005, 05:43 CET | Link
shjava
Readonly transaction and second level cache: If you use transactions for read only operations then It lookis like hibernate opens a connection and sends a transaction begin call to data base even entire data is in second level cache.. why is it doing? this is unnecssary overhead right? if we find all data in second level cache why do we need to open a connection ? FYI: if we do not use transaction then hibernate does not open a connection and no call to DB..
 
07. Nov 2006, 16:03 CET | Link
tero
Hi! It's an interesting article, but I don't see why you would want to create a new instance of the command and new instances of all DAOs every time you use them. Is there something wrong with using singleton DAOs ("manual" singletons or Spring) and giving DAOs the HibernateSessionFactory so they can get the current session from there, or alternatively passing the HibernateSession to each DAO method as a parameter? As far as I can tell there should be nothing in the generic DAO that requires a new instance every time, or is there something I'm missing?
 
25. Feb 2007, 08:16 CET | Link
It's a good idea to have a GenericDAO. I like the use of generics in this case, although I'm sure you are aware of the pitfalls in using generics (http://www.agiledeveloper.com/presentations/GoodBadAndUglyOfJavaGenerics.zip).

Unfortunately, in this pattern it is not clear what "makePersistent" and "makeTransient" really do. At first glance, I would think "makeTransient" could mean either detach the instance or remove it, but unless I look at the code I would not know. Following with this idea, where are "makeMerged" or "makeDetached"? It would seem this interface is incomplete without them.

Adhering to the standard naming practices set by JPA would resolve this; why not call it, "persist", "merge" and "remove"? Why create a new set of function names? And for what benefit?

Secondly, it would be even better to have one DAO to rule them all, and not have to make empty concrete implementations, only to specify the entity class name. Having to couple the entity class name to the method will likely become unmaintainable quickly.

According to the Open-Closed Principle (http://www.objectmentor.com/resources/articles/ocp.pdf) if we decide to remove Category, for example, there should be no need to change the FactoryDAO, but according to this implementation, we would have to remove the "getCategoryDAO" from every implementation of DAOFactory.

I look forwrad to future revisions of this pattern and thank you for posting this.

Tan
 
05. Apr 2010, 07:46 CET | Link
Marco

Hi,

when is the transaction committed?

 
23. Jul 2010, 12:19 CET | Link
Ajay
Hello Christian,

I need some help on below point of empty interfaces for each entity,

"However, even if only CRUD operations are needed for a particular entity, you should still write an interface for it, even if it is going to be empty. It is important to use a concrete DAO in your controller code, otherwise you will face some refactoring once you have to introduce specific data access operations for this entity."

I used this pattern for my project but my colleagues want to remove the empty interfaces saying that it is unnecessary.

So lets say ItemDAO is empty then they want to directly use ItemDAOHibernate and refer it using GenericDAO reference like this,

GenericDAO<Item, Long> itemDAO = factory.getItemDAO();

Now this also triggers change in my factory interface and implementation.

Is this good? Is there any trap/problem here that cannot be seen?

I do not have much problem with empty interfaces for 2 reasons,
1. If in future I have to add methods I do not need to refactor
2. Also it is natural to get ItemDAO do do Item things then get GenericDAO.

Please Help.

-Ajay



 
24. Jun 2014, 12:56 CET | Link

Beside of that, bank turn to a financial firm that known as a dealers which are involved in large number of foreign exchange market trading. In foreign exchange market, Banks are the most forex market dealers. For this reason, sometime it also called interbank market. Some insurance companies and financial firms are involving in this part A basic skill a Forex trader has to acquire is how to read forex quote .It will help the newbie trader read and interpret Forex quotes