论坛首页 Java企业应用论坛

DAO的设计

浏览 15458 次
锁定老帖子 主题:DAO的设计
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2007-05-28  
DAO
学Hibernate有一段时间了,
最初我是这么设计的:
package com.zjut.DAO;

import java.util.List;

import com.zjut.PO.User;
public interface UserDAO {
public List getUsers();
public User getUserByID(int id);
public boolean deleteUserByID(int id);
public boolean updateUser(User user);
public boolean saveUser(User user);
//public List userList(int PageSize,int startRow);
//public int getUserRows(String query);
}

然后就用一个类来实现这个接口....这样就完了, 因为User的操作不是很多, 我就在想没有必要来加个基接口了吧 ...
后来:
按照rainlife大哥的设计思想 :
这里引用rainlife大哥的帖子


首先定义DAO类的接口IGenericDAO,该接口定义了共同的CRUD操作:

java 代码
 
/**  
 * 定义通用的CRUD操作  
 * @author rainlife  
 */   
public interface IGenericDAO 〈T, ID extends Serializable〉 
{   
//  通过主键标识查找某个对象。   
    public T findById(ID id);   
       
//  通过主键标识查找某个对象,可以锁定表中对应的记录。   
    T findById(ID id, boolean lock);   
   
    //得到所有的对象。   
    List findAll();   
   
    //通过给定的一个对象,查找与其匹配的对象。   
    List findByExample(T exampleInstance);   
   
    //持久化对象。   
    T makePersistent(T entity);   
   
    //删除对象。   
    void makeTransient(T entity);   
}   


下面是使用Hibernate针对该接口的实现GenericDAOHibernate:

java 代码
 
/**  
 * 这是针对IGenericDAO接口的Hibernate实现,完成通用的CRUD操作。  
 * @author rainlife  
 * @param  POJO类  
 * @param   POJO类的主键标识符  
 * @param  针对每一个POJO类的DAO类实现   
 */   
public abstract class GenericDAOHibernate 〈T,ID extends Serializable, DAOImpl extends IGenericDAO〈T,ID〉〉 
        implements IGenericDAO〈T,ID〉 
{   
    private Class persistentClass;   
   
    protected Session session;   
   
    public GenericDAOHibernate()   
    {   
        this.persistentClass = (Class) ((ParameterizedType) getClass()   
                .getGenericSuperclass()).getActualTypeArguments()[0];   
    }   
   
    @SuppressWarnings("unchecked")   
    public DAOImpl setSession(Session s)   
    {   
        this.session = s;   
        return (DAOImpl)this;   
    }   
   
    protected Session getSession()   
    {   
        if (session == null)   
            throw new IllegalStateException(   
                    "Session has not been set on DAO before usage");   
        return session;   
    }   
   
    public Class getPersistentClass()   
    {   
        return persistentClass;   
    }   
   
       
    @SuppressWarnings("unchecked")   
    public T findById(ID id)   
    {   
        return (T) getSession().load(getPersistentClass(), id);   
    }   
       
    @SuppressWarnings("unchecked")   
    public T findById(ID id, boolean lock)   
    {   
        T entity;   
        if (lock)   
            entity = (T) getSession().load(getPersistentClass(), id, LockMode.UPGRADE);   
        else   
            entity = findById(id);   
   
        return entity;   
    }   
   
    @SuppressWarnings("unchecked")   
    public List findAll()   
    {   
        return findByCriteria();   
    }   
   
    @SuppressWarnings("unchecked")   
    public List findByExample(T exampleInstance)   
    {   
        Criteria crit = getSession().createCriteria(getPersistentClass());   
        Example example = Example.create(exampleInstance);   
        crit.add(example);   
        return crit.list();   
    }   
       
    @SuppressWarnings("unchecked")   
    public List findByExample(T exampleInstance, String[] excludeProperty)   
    {   
        Criteria crit = getSession().createCriteria(getPersistentClass());   
        Example example = Example.create(exampleInstance);   
        for (String exclude : excludeProperty)   
        {   
            example.excludeProperty(exclude);   
        }   
        crit.add(example);   
        return crit.list();   
    }   
   
    @SuppressWarnings("unchecked")   
    public T makePersistent(T entity)   
    {   
        getSession().saveOrUpdate(entity);   
        //getSession().save(entity);   
        return entity;   
    }   
   
    public void makeTransient(T entity)   
    {   
        getSession().delete(entity);   
    }   
   
    @SuppressWarnings("unchecked")   
    protected List findByCriteria(Criterion... criterion)   
    {   
        Criteria crit = getSession().createCriteria(getPersistentClass());   
        for (Criterion c : criterion)   
        {   
            crit.add(c);   
        }   
        return crit.list();   
    }   
       
    @SuppressWarnings("unchecked")   
    /**  
     * 增加了排序的功能。  
     */   
    protected List findByCriteria(Order order,Criterion... criterion)   
    {   
        Criteria crit = getSession().createCriteria(getPersistentClass());   
        for (Criterion c : criterion)   
        {   
            crit.add(c);   
        }   
        if(order!=null)   
            crit.addOrder(order);   
        return crit.list();   
    }   
       
    @SuppressWarnings("unchecked")   
    protected List findByCriteria(int firstResult,int rowCount,Order order,Criterion... criterion)   
    {   
        Criteria crit = getSession().createCriteria(getPersistentClass());   
        for (Criterion c : criterion)   
        {   
            crit.add(c);   
        }   
        if(order!=null)   
            crit.addOrder(order);   
        crit.setFirstResult(firstResult);   
        crit.setMaxResults(rowCount);   
        return crit.list();   
    }   
}   


这样,我们自己所要使用的DAO类,就可以直接从这个Hibernate的DAO类继承:

比如说我们定义一个IUserDAO接口,该接口继承IGenericDAO:


java 代码
public interface IUserDAO extends IGenericDAO〈User,Integer〉 
{   
    public User find(String username,String password);   
    public User find(String username);   
}   

 

该接口从IGenericDAO继承,自然也就定义了IGenericDAO接口所定义的通用CRUD操作。


再来看一下针对IUserDAO 的Hibernate实现UserDAOHibernate:


java 代码
public class UserDAOHibernate extends GenericDAOHibernate〈User,Integer,IUserDAO〉 implements IUserDAO {       

   
    public User find(String username, String password) {   
        //此处省略具体代码   
    }   
   
    public User find(String username) {   
        //此处省略具体代码   
    }   
}   

 

UserDAOHibernate继承GenericDAOHibernate并实现IUserDAO接口,这样,我们的UserDAOHibernate既拥有通用的CRUD操作,也实现了针对用户的特定的业务操作。






但是我在想如果在一个PO对象的操作不是很多的时候有必要分这么多的层次吗....
可能是我学的不够好.....  大家来聊聊吧
   发表时间:2007-05-28  
我想你首先要了解为什么要使用接口,接口是为了方便以后扩展,使用了接口,当你以后需要更改实现的话,仅仅只需要增加一个实现,而非去修改原有的实现,而实现类可动态注入到应用中,这样就不用修改客户端代码,以达到解藕的目的。
0 请登录后投票
   发表时间:2007-05-28  
额..........  接口的作用我知道,但是接口上面加上一个基接口,没想错的话应该是在继承的接口避免重复CURD操作,但我想问的是如果一个类的操作少的话加个基接口好像没什么好的吧
0 请登录后投票
   发表时间:2007-05-28  
接口的设计就是要逻辑清析
基接口是为了与数据库层配合(通用方法)

业务特色由子接口来描述。。。
(如果没有特色业务可用考虑用同一个接口不同的实现来完成。)
0 请登录后投票
   发表时间:2007-05-28  
那你该设计时就应该像到,想不到就在你感到在做重复性工作时,就该思考如何重构了,使得更加自然。
0 请登录后投票
   发表时间:2007-05-28  
继承于一个基接口最大的好处就是避免了你重复性的定义一些通用操作,这是最有价值的.
0 请登录后投票
   发表时间:2007-06-11  
比如 你对user表 和userinfo表都要作一个根据主件查询 就可以在接口里面声明  在 接口的实现类的基类里面实现 然后 userDao 和userinfoDao都继承自基类  就可以实现 主表查询.[这里只是比喻 不考虑 user 表和 userinfo表是否违法范式]
0 请登录后投票
   发表时间:2007-06-11  
有些公认为最佳实践的设计可以直接沿用

Templete Dao 和 衍生的范性 Templete Dao 都是这样的例子
0 请登录后投票
   发表时间:2007-06-12  
hibbernate 是可以生成自动的数据岛 但是呢 好像很多都是没有用的  个人来说 不是太喜欢 呵呵 还是喜欢自己写个抽象dao
0 请登录后投票
   发表时间:2007-06-29  
写得不错!!
清晰易懂!!
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics