views:

700

answers:

3

I'm using Hibernate. The question is at the bottom.

The current strategy

It's simple.

First of all, I have a basic Dao<T>.

public class Dao<T> {
    private Class<T> persistentClass;
    private Session session;

    public Dao(Class<T> persistentClass) {
        this.persistenClass = persistentClass;
        this.session = HibernateUtil.getCurrentSession();
    }

It's nice as a base class and it passes the most common methods up to its Session.

    public T get(Serializable id) {
        @SuppressWarnings("unchecked")
        T t = (T) this.session.get(this.persistentClass, id);

        return t;
    }

    protected Criteria getCriteria() {
        return this.session.createCriteria(this.persistentClass);
    }

When there's need to use queries on the model, it goes into a specific DAO for that piece of model, which inherits from Dao<T>.

public class DaoTask extends Dao<Task> {
    public DaoTask() {
        super(Task.class);
    }

    public List<Task> searchActiveTasks() {
        @SuppressWarnings("unchecked")
        List<Task> list = (List<Task>) this.getCriteria()
            .add(Restrictions.eq("active", true))
            .list();

        return list;
    }
}

This approach has always worked well.

However...

However, today I found that many times an instance needs reattachment to the Session and a line similar to the following ends up happening:

new Dao<Book>(Book.class).update(book);

... which I find to be bad, because

  1. I don't like specifying the redundant Book.class
  2. If ever a DaoBook arises, this construct will become obsolete.

So I turned Dao<T> into an abstract class, and went on to refactor the old code.

Question

In order to remove the Dao<T> references from the codebase, I thought of two approaches:

  1. Create specific DAOs for every class that ever needs attachment, which would generate many almost empty DaoBooks and the sort.
  2. Create a class that owns a Dao<Object> and exposes only the attachment methods (i.e. save(), update() etc).

I'm tending to go with #2, but I thought this "AttacherDao" pattern might be bad, so I'd like your opinion.

Any cons for #2? Also, do you find anything wrong with "the current strategy"?

+1  A: 

Couple of questions

  1. Are you frequently creating your DOA to do a single task or are these long lived?
  2. What about using a static function? Clearly your Book object can be bind the DOA function to without the Book.class reference...

Otherwise, I'm a little worried about keeping the session object around instead of fetching whatever the current session is - isn't it considered "bad" to have long lived session objects? I'm not a master of DOA, so maybe I'm missing something here.

Petriborg
DAOs are short-lived. Sessions are open just as long as the user request is being processed.
André Neves
+1  A: 

Our approach is to have a DAO object (derived from a commonDao) for each persistent class. In fact we define interface for this DAO class and each DAO decides which interfaces are opened up.

Using the following code, user cannot delete the PersistentClass.

interface PersistentClassDao {
    void save(PersistentClass persistentObject);    
}

Class PersistentClassDaoImpl extends CommonDao implements PersistentClassDao {
       void save(persistentObject) {
    persist(persistentObject);
}

Even though it has some additional overhead, this approach helps in unit testing appropriate code before exposing an interface.

lud0h
So your suggestion is to have an interface to each "business operation", ie DeletableClassDao, UpdatableClassDao etc?
André Neves
No. There will be only one DAO for a business object not for a business operation, e.g. BookDao and BookDao will encapsulate all operations on Book object and can decide whether users can "save", "update" and/or "delete".
lud0h
A: 

We've chosen an approach similar to lud0h's, with the following twist:

abstract class<T extends IModelObject> JdbcCrudDao<T>{

   void create(T dbo){}
   T findByFoo(String foo){}
   void update(T dbo){}
   void delete(T dbo){}

}

class BarDao extends JdbcCrudDao<Bar>{

}

But, the twist is that we selectively expose methods on the Dao through a facade and forward only those we absolutely must.

class BarController implements IController{

    private static final BarDao dao;
    // ...

    void update( IBar bar ){
       dao.update(bar);
    }

}

The only short-coming in all this is it requires some casting about if you wish to hide your database keys behind an interface type (which we do), but it's a pretty minor inconvenience versus the alternative (database code outside of the Daos).

jasonnerothin
I think your brevity confused things for me. Does JdbcCrudDao implement anything or are those really empty or abstract methods? Same for BarDao!
André Neves