-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 22 posts ]  Go to page Previous  1, 2
Author Message
 Post subject: Re: Another DAO using Generics [repost with formatted code]
PostPosted: Sat Oct 01, 2005 4:17 pm 
Regular
Regular

Joined: Thu Feb 17, 2005 1:58 am
Posts: 63
Mikhail,

This looks pretty cool. It looks like I can implement the same deal without generics too, no?


mgrouch wrote:
I'm using the following DAO implementation for hibernate, which
I'd like to share on this forum to get other people opinions.

It is using java 5.0 generics and is based on the code found at
http://www.ericburke.com/blog/2004/11/h ... ava-5.html

with the difference that id class is also parameterized.

Basically when creating your own DAO you usually only need to write
finder methods

Here is an example of using this generic DAO class

Code:

public class CategoryDAO extends GenericDAO<Category, Long> {
  public CategoryDAO() {
    super(Category.class, Long.class);
  }

public List<Category> getRootCategories() {
    return get(Expression.isNull("parentCategory"));
  }
}



Please, let know what do you think of this approach.

Thanks a lot


Code:
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.LockMode;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.criterion.Criterion;

public abstract class GenericDAO<T extends Serializable, K extends Serializable> {

   private Class persistentClass;
   private Class idClass;

   private static Log log = LogFactory.getLog(GenericDAO.class);

   protected Session currentSession() {
      return HibernateUtil.currentSession();
   }

   /**
    * Constructor
    *
    * @param persistentClass
    * @param idClass
    */
   public GenericDAO(Class persistentClass, Class idClass) {
      this.persistentClass = persistentClass;
      this.idClass = idClass;
      currentSession().beginTransaction();
   }

   /**
    * @return Returns the idClass.
    */
   public Class getIdClass() {
      return idClass;
   }

   /**
    * @return Returns the persistentClass.
    */
   public Class getPersistentClass() {
      return persistentClass;
   }

   /**
    * Persist entity in database
    *
    * @param entity
    */
   public void persist(T entity) {
      Session session = null;

      try {
         session = currentSession();
         session.persist(entity);
      } catch (HibernateException ex) {
         log.error(ex.getMessages());
         throw new DaoException(ex);
      }
   }

   /**
    * Save entity in database
    *
    * @param entity
    */
   public void save(T entity) {
      Session session = null;

      try {
         session = currentSession();
         session.save(entity);
      } catch (HibernateException ex) {
         log.error(ex.getMessages());
         throw new DaoException(ex);
      }
   }

   /**
    * Save or update entity in database
    *
    * @param entity
    */
   public void saveOrUpdate(T entity) {
      Session session = null;

      try {
         session = currentSession();
         session.saveOrUpdate(entity);
      } catch (HibernateException ex) {
         log.error(ex.getMessages());
         throw new DaoException(ex);
      }
   }

   /**
    * Delete entity in database
    *
    * @param entity
    */
   public void delete(T entity) {
      Session session = null;

      try {
         session = currentSession();
         session.delete(entity);
      } catch (HibernateException ex) {
         log.error(ex.getMessages());
         throw new DaoException(ex);
      }
   }

   /**
    * Delete all entities
    */
   public void deleteAll() {
      Session session = null;

      try {
         session = currentSession();
         session.delete("from " + getPersistentClass().getName() + " x");

      } catch (HibernateException ex) {
         log.error(ex.getMessages());
         throw new DaoException(ex);
      }
   }

   /**
    * Find entity by ID
    *
    * @param id
    * @param lock
    * @return entity
    */
   @SuppressWarnings("unchecked")
   public T getById(K id, boolean lock) {
      T entity = null;

      try {
         if (lock) {
            entity = (T) currentSession().get(getPersistentClass(), id,
                  LockMode.UPGRADE);
         } else {
            entity = (T) currentSession().get(getPersistentClass(), id);
         }
      } catch (HibernateException ex) {
         log.error(ex.getMessages());
         throw new DaoException(ex);
      }

      return entity;
   }

   /**
    * Get all
    *
    * @return list of entities
    */
   @SuppressWarnings("unchecked")
   public List<T> getAll() {
      List<T> list = null;
      Session session = null;
      Query query = null;

      try {
         session = currentSession();
         query = session.createQuery("from "
               + getPersistentClass().getName() + " x");
         list = query.list();
      } catch (HibernateException ex) {
         throw new DaoException(ex);
      }

      return list;
   }

   /**
    * This is the cool finder method
    *
    * @param criterion
    * @return list of entities
    */
   @SuppressWarnings("unchecked")
   public List<T> get(Criterion... criterion) {
      List<T> list = null;

      Criteria criteria = currentSession().createCriteria(
            getPersistentClass());

      try {
         for (Criterion c : criterion) {
            criteria.add(c);
         }

         list = new ArrayList<T>(criteria.list());
      } catch (HibernateException ex) {
         throw new DaoException(ex);
      }

      return list;
   }
}

[/code]


Top
 Profile  
 
 Post subject: Re: Another DAO using Generics [repost with formatted code]
PostPosted: Sat Oct 01, 2005 8:36 pm 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
hiberdude wrote:
Mikhail,

This looks pretty cool. It looks like I can implement the same deal without generics too, no?


No, using generics is the real trick here. You can't simulate that and get the "same deal".


Top
 Profile  
 
 Post subject: Re: Another DAO using Generics [repost with formatted code]
PostPosted: Sat Oct 01, 2005 9:58 pm 
Regular
Regular

Joined: Thu Feb 17, 2005 1:58 am
Posts: 63
christian wrote:
hiberdude wrote:
Mikhail,

This looks pretty cool. It looks like I can implement the same deal without generics too, no?


No, using generics is the real trick here. You can't simulate that and get the "same deal".


Well, how about I just use "Object" ? I lose type checking and I need to cast, but beside that, I should be able to get really close. Or did I miss something essential?


Top
 Profile  
 
 Post subject:
PostPosted: Sat Oct 01, 2005 10:05 pm 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
But then its just a trivial DAO pattern like everybody already has, no? Also, I wouldn't give up compile-time safety for runtime errors. Your choice...


Top
 Profile  
 
 Post subject: Just try it
PostPosted: Mon Oct 03, 2005 4:37 pm 
Beginner
Beginner

Joined: Thu Aug 04, 2005 8:41 pm
Posts: 47
Quote:
Well, how about I just use "Object" ? I lose type checking and I need to cast, but beside that, I should be able to get really close. Or did I miss something essential?


Try it. You would have AbstractDAO class and DAOs extending it.
In those DAOs you would want to hide type unsafe methods like
save(Object o) and expose safe ones. Like ex

CategoryDAO:

save(Category o).

It will make your DAOs code bigger than with generics and you might find some other tricks needed. I think it is still worth trying. :)

I do not think it is exactly what people usually have for DAOs. DAOs I saw
had lot of exception handling and other things which should have not been in there.

--MG


Top
 Profile  
 
 Post subject:
PostPosted: Mon Oct 03, 2005 7:51 pm 
Beginner
Beginner

Joined: Sat Sep 17, 2005 10:41 am
Posts: 49
Christian, et. al.

I just noticed this quote.

Quote:
I use single ID because that is what people _should_ do.


However, some people would say it's good practice to use natural primary keys when possible (for example, using ISO country codes for a Country entity).

Clearly, we have a pattern mismatch.

I sort of got around the problem by creating a parallel hierarchy of entities and DAOs, then only exposing the id's as type String.

Code:
public abstract class EntityDao<T extends Entity, ID extends Serializable> {
  protected T _find (ID id) {
     ...
  }
  public abstract T find (String id) ;
}

public class NaturalDao<T extends NaturalEntity>  extends EntityDao <T, String> {
  public T find (String id) {
   super._find (id) ;
  }

}

public class BasicDao<T extends BasicEntity>
  extends EntityDao <T, Long> {
  public T find (String id) {
    super._find (Long.parseLong (id)) ;
  }
  public T find (Long id) {
    super._find (id) ;
  }
}


where (all entities use access-type="field")...

Code:
@EmbeddableSuperclass (access = AccessType.FIELD)
public abstract class Entity {
  public abstract String getId () ;
}

@EmbeddableSuperclass (access = AccessType.FIELD)
public class NaturalEntity extends Entity {
  @Id
  String id ;
  ...
  public String getId () { return id ; }
}

@EmbeddableSuperclass (access = AccessType.FIELD)
public class BasicEntity extends Entity {
  @Id
  Long id ;
  ...
  public String getId () { return (id == null) ? null : id.toString() ; }
}



Top
 Profile  
 
 Post subject:
PostPosted: Tue Oct 04, 2005 12:58 am 
Hibernate Team
Hibernate Team

Joined: Mon Aug 25, 2003 9:11 pm
Posts: 4592
Location: Switzerland
Quote:
However, some people would say it's good practice to use natural primary keys when possible (for example, using ISO country codes for a Country entity).


That is not what I said. I'm all for good natural keys, when appropriate for my data model. However, I said _composite_ keys are no good, which is different. In any case, the DAO source code that made it into the examples supports any key type.


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 22 posts ]  Go to page Previous  1, 2

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.