• 通用Hibernate-Dao


    在做管理系统时。通常基于Facade模式的系统持久化层要写许多Dao。这些dao里面的方法又是重复的,那么有没有什么好的方法来统一利用一个公共的Dao。 

    答案是可以的。这里我们接触到JDK5.0里面的一个新特性:泛型。 

    关于泛型的含义我这里就不再解释了。 

    下面我们以一个对用户管理和新闻管理的来示范。 

    首先是2个POJO。我这里只列出User  POJO。 
    (基于注释的Pojo)

    package com.oa;  
      
    import javax.persistence.Column;  
    import javax.persistence.Entity;  
    import javax.persistence.GeneratedValue;  
    import javax.persistence.GenerationType;  
    import javax.persistence.Id;  
    import javax.persistence.Table;  
      
    @Entity  
    @Table(name = "tb_user")  
    public class User {  
      
        @Id  
        @GeneratedValue(strategy = GenerationType.IDENTITY)  
        private int id;  
      
        @Column(name = "username", length = 15)  
        private String username;  
      
        @Column(name = "password", length = 15)  
        private String password;  
      
        public int getId() {  
            return id;  
        }  
      
        public void setId(int id) {  
            this.id = id;  
        }  
      
        public String getUsername() {  
            return username;  
        }  
      
        public void setUsername(String username) {  
            this.username = username;  
        }  
      
        public String getPassword() {  
            return password;  
        }  
      
        public void setPassword(String password) {  
            this.password = password;  
        }  
      
    }  
      
     

    如果按照常规的Facade模式来设计,我们的思路是: 
    先创建一个UserDao的接口。 

    package com.oa.dao;  
      
    import java.util.List;  
      
    import com.oa.User;  
      
    public interface UserDao {  
        public void save(User user);  
      
        public void delete(int id);  
      
        public void update(User user);  
      
        public List<User> query();  
      
        public User get(int id);  
      
    }  
      

    然后实现这个接口:UserDaoImpl 

    package com.oa.dao.impl;  
      
    import java.util.List;  
      
    import org.springframework.context.annotation.Scope;  
    import org.springframework.stereotype.Repository;  
      
    import com.oa.User;  
    import com.oa.dao.MyHibernateDaoSupport;  
    import com.oa.dao.UserDao;  
      
      
      
    /** 
     * 从Spring 2.0开始,引入了@Repository注解, 
     *  用它来标记充当储存库(又称 Data Access Object或DAO)角色或典型的类 
     */  
      
      
    /** 
     * Spring 2.5引入了更多典型化注解(stereotype annotations): @Component、@Service和 @Controller。  
     * @Component是所有受Spring管理组件的通用形式; 而@Repository、@Service和 @Controller则是@Component的细化,  
     *                   用来表示更具体的用例(例如,分别对应了持久化层、 服务层  和   表现层)。 
     */  
    //@Scope("singlton")  
    @Repository("userDao")//声明此类为数据持久层的类  
    public class UserDaoImpl extends MyHibernateDaoSupport implements UserDao {  
      
        public void delete(int id) {  
            super.getHibernateTemplate().delete(  
                    super.getHibernateTemplate().load(User.class, id));  
      
        }  
      
        public User get(int id) {  
      
            return (User) super.getHibernateTemplate().get("from  User", id);  
        }  
      
        @SuppressWarnings("unchecked")  
        public List<User> query() {  
            return super.getHibernateTemplate().find("from User");  
      
        }  
      
        public void save(User user) {  
            super.getHibernateTemplate().save(user);  
      
        }  
      
        public void update(User user) {  
            super.getHibernateTemplate().update(user);  
      
        }  
      
    }  

    持久化层完毕。 


    接下来的是事务层 


    先创建一个UserService的接口

    package com.oa.service;  
      
    import com.oa.User;  
      
    public interface UserService {  
          
        public void save(User user);  
      
        public void update(User user);  
      
    }  

    然后实现这个接口:UserServiceImpl。 
    在UserServiceImpl里引用UserDao来实现业务逻辑。 

    package com.oa.service.impl;  
      
    import com.oa.User;  
    import com.oa.service.UserService;  
    import com.oa.dao.UserDao;  
      
      
    import java.util.List;  
      
    import org.springframework.beans.factory.annotation.Autowired;  
    import org.springframework.stereotype.Service;  
      
      
      
    /** 
     * 声明此类为业务逻辑层的类 
     * 默认bean名称生成器会返回小写开头的非限定(non-qualified)类名 
     * @Service 
     * userServiceImpl 
     */  
    @Service("userService")  
    public class UserServiceImpl implements UserService {  
      
          
        /** 
         * @Autowired 
         *  
         * @Autowired 注解可以用于"传统的"setter 方法,如下例: 
         * public void setUserDao(UserDAO userDao) 
        { 
            this.userDao = userDao; 
        } 
         */  
          
        /** 
         * @Resource有一个'name'属性,缺省时,Spring 将这个值解释为要注射的 bean 的名字。 
         *   @Resource(name="userDao")  
         */  
        @Autowired //  or  @Resource(name="userDao")  
        private UserDao userDao;  
      
        public void save(User user) {  
            userDao.save(user);  
      
        }  
      
        public void update(User user) {  
            userDao.update(user);  
      
        }  
      
    }  
      
       

    按照上面的模式:新闻管理也这么写一遍。 

    重复的工作使得我们觉得好烦。 


    这个时候是泛型出场的时候了。 

    基于Facade的设计模式,dao和service还是要的。 这里我们就要设计一个公共的Dao..  我们称之为:GenericDao 

    package com.oa.dao;  
      
    import java.io.Serializable;  
    import java.util.*;  
      
    /** 
     * * 
     *  
     * @param <T> 
     *            泛型,指实体类  type 
     * @param <PK> 
     *            泛型,指实体类主键的数据类型,如Integer,Long 
     */  
    public interface GenericDao<T, PK> {  
          
        /**   
         * 保存指定实体类   
         *    
         * @param entityobj   
         *            实体类   
         */   
        public  void save(T entity);  
          
          
          /**   
         * 删除指定实体   
         *    
         * @param entityobj   
         *            实体类   
         */    
        public void delete(T entity);  
          
          
         /** * 
         * 删除实体 
         * @param entityClass 实体类名 
         * @param id 实体的ID 
         */  
        public void deleteById(Class<T> entityClass,PK id);  
          
          
        /**   
        * 更新或保存指定实体   
        *    
        * @param entity 实体类   
        */   
        public void saveorupdate(T entity);  
          
          
         /** * 
         * 更新实体 
         * 可用于添加、修改、删除操作 
         * @param hql 更新的HQL语句 
         * @param params 参数,可有项目或多项目,代替Hql中的"?"号 
         */  
        public void update(final String hql,final Object[] params);  
          
          
      
        /**   
         * 模糊查询指定条件对象集合 <br>   
         * 用法:可以实例化一个空的T对象,需要查询某个字段,就set该字段的条件然后调用本方法<br>   
         * 缺点:目前测试貌似只能支持String的模糊查询,虽然有办法重写,但没必要,其他用HQL<br>   
         *    
         * @param entity   
         *            条件实体   
         * @return 结合   
         */    
        public List<T> findByExample(T entity);  
          
          
        /**   
         * 获取所有实体集合   
         *    
         * @param entityClass   
         *            实体   
         * @return 集合   
         */    
        public List<T> findAll(Class<T> entityClass);  
          
        public List<T> findAll(Class<T> entityClass,String hql,Object[] params,int start, int limit);  
        /**   
         * 查找指定PK实体类对象   
         *    
         * @param entityClass   
         *            实体Class   
         * @param id   
         *            实体PK   
         * @return 实体对象   
         */     
        public T findById(Class<T> entityClass, PK id);  
          
        /** * 
         * 按HQL条件查询列表 
         * @param hql 查询语句,支持连接查询和多条件查询 
         * @param params 参数数组,代替hql中的"?"号 
         * @return 结果集List 
         */  
         
        public List<T> findByHql(String hql,Object[]  params);  
          
        /**   
         * 查找指定属性的实体集合   
         *    
         * @param entityClass   
         *            实体   
         * @param propertyName   
         *            属性名   
         * @param value   
         *            条件   
         * @return 实体集合   
         */    
        public List<T> findByProperty(Class<T> entityClass, String propertyName,Object value);  
          
          
        /**   
         * 查询指定HQL语句的分页数据集合   
         *    
         * @param hsql   
         *            HQL语句   
         * @param start   
         *            开始记录号   
         * @param limit   
         *            最大记录号   
         * @return 分页数据集合   
         * @throws Exception   
         *             抛出异常   
         */    
        public List<T> findByPage(Class<T> entityClass,int start,int limit) ;  
          
          
          
        /** 
         * 获得总记录数 
         */  
        public T getTotalCount(Class<T> entityClass);  
          
        public T getPageCount(String hql,Object[] params);  
      
    }  
       

    看到,我们不再是具体的User , News 
    。。而是用 T  来取代实体。 


    因为我这个是基于 注解的,所以附上MyHibernateDaoSupport的代码。 

    package com.oa.dao;  
      
    import javax.annotation.Resource;  
    import org.hibernate.SessionFactory;  
    import org.springframework.orm.hibernate3.support.HibernateDaoSupport;  
      
    /** 
     * 我们之所以要改写 
     * HibernateDaoSupport,是因我为,我们要为DAO层的类注入SessionFactory这个属性。 
     * 以后,我们开发的DAO类,就可以直接重用这个MyHibernateDaoSupport了。 
     * 其实,这样做是相当于配置文件方式的代码: 
     * <bean id="userDao" class="com.oa.dao.UserDaoImpl">  
     * <property 
     * name="sessionFactory" ref="sessionFactory"/>  
     * </bean> 
     *  
     * @author Administrator 
     *  
     */  
    public class MyHibernateDaoSupport extends HibernateDaoSupport {  
          
        @Resource(name="sessionFactory")    //为父类HibernateDaoSupport注入sessionFactory的值  
        public void setSuperSessionFactory(SessionFactory sessionFactory){  
            super.setSessionFactory(sessionFactory);  
        }  
          
      
    }  
      

    到现在位置genericdao的接口有了,也就是我们要做什么。。现在就是实现它,就是怎么做。 
    GenericDaoImpl 代码: 

    package com.oa.dao.impl;  
      
    import java.io.Serializable;  
    import java.util.List;  
      
    import org.hibernate.Query;  
    import org.springframework.stereotype.Repository;  
      
    import com.oa.dao.GenericDao;  
    import com.oa.dao.MyHibernateDaoSupport;  
    @SuppressWarnings("unchecked")  
    @Repository("genericDao")   //声明此类为数据持久层的类  
    public class GenericDaoImpl<T, PK extends Serializable> extends  
                                        MyHibernateDaoSupport implements GenericDao<T, PK> {  
      
        public void delete(T entity) {  
            super.getHibernateTemplate().delete(entity);  
        }  
      
      
        public void deleteById(Class entityClass, PK id) {  
            super.getHibernateTemplate().delete(findById(entityClass, id));  
      
        }  
          
        public void save(T entity) {  
            super.getHibernateTemplate().save(entity);  
      
        }  
      
        public void saveorupdate(T entity) {  
            super.getHibernateTemplate().saveOrUpdate(entity);  
      
        }  
      
        public void update(String hql, Object[] params) {  
                 Query query = super.getSession().createQuery(hql);  
                    for(int i=0; i<params.length; i++){  
                        query.setParameter(i, params[i]);  
                    }  
                    query.executeUpdate();  
         }  
          
      
        public List<T> findAll(Class entityClass) {  
              
            return super.getHibernateTemplate().loadAll(entityClass);  
        }  
      
        public List<T> findAll(Class entityClass, String hql, Object[] params,int start, int limit) {  
            Query query = super.getSession().createQuery(hql);  
            if(params!=null&&params.length>0){  
                for(int i = 0;i<params.length;i++){  
                    query.setParameter(i, params[i]);  
                }  
            }  
            if(start!=0&&limit!=0){  
                query.setFirstResult(start).setMaxResults(limit);  
            }  
            return query.list();  
        }  
      
        public List<T> findByExample(T entity) {  
            return super.getHibernateTemplate().findByExample(entity);  
        }  
      
        public List<T> findByHql(String hql, Object[] params) {  
            Query query = super.getSession().createQuery(hql);  
            if(null!= params && params.length>0){  
                for(int i = 0; i<params.length;i++){  
                    query.setParameter(i, params[i]);  
                }  
            }  
            return query.list();  
        }  
      
        public T findById(Class entityClass, PK id) {  
            return (T)super.getHibernateTemplate().get(entityClass, id);  
        }  
          
        public List<T> findByProperty(Class entityClass, String propertyName,Object value) {  
            String queryString = "from "+entityClass.getName()+ " as model where model." + propertyName + "=?";     
            return super.getHibernateTemplate().find(queryString, value);  
        }  
      
      
          
        //分页使用  
        public List<T> findByPage(Class<T> entityClass,int start,int limit) {  
              Query query=super.getSession().createQuery("select o from "+entityClass.getName()+" o");  
              query.setFirstResult(start).setMaxResults(limit);  
            return query.list();  
        }  
      
          
        public T getTotalCount(Class entityClass) {  
              
            return (T)super.getSession().createQuery("select count(o) from "+entityClass.getName()+" o").uniqueResult();  
        }  
      
        public T getPageCount(String hql, Object[] params) {  
            Query query = super.getSession().createQuery(hql);  
            if(null!= params && params.length>0){  
                for(int i = 0; i<params.length;i++){  
                    query.setParameter(i, params[i]);  
                }  
            }  
            return (T)query.list();  
        }  
      
          
      
    } 


    至此 泛型就告一个段落。 


    接下来日子就好过了。 

    我们不是有user  news   等等一系列的curd管理。 


    以User为例子; 
    定义一个user的接口, 
    UserDao.Java 

    package com.oa.dao;  
      
    import com.oa.User;  
      
    public interface UserDao extends GenericDao<User, Integer> {  
      
    public   int   login(User user);  
    //其他的方法的  
    }  
      
      
    然后就是实现它 UserDaoImpl  
      
    package com.oa.dao.impl;  
      
      
      
    import com.oa.User;  
    import com.oa.dao.UserDao;  
      
    public class UserDaoImpl extends GenericDaoImpl<User, Integer> implements UserDao {  
      
        public  int  login(User  user){  
    //登陆判断的方法  
      
    return   XX;  
    };  
      
      
    //其他的方法的实现  
      
      
    }  
      

    持久化层就是这么多了。 

    下面进入业务逻辑层,依然是先定义一个接口。 

    package com.oa.service;  
      
    import com.oa.User;  
      
    public interface UserService {  
          
        public void save(User user);  
      
        public void update(User user);  
      
       public  int  login(User  user);  
      
    //其他的方法  
      
    }  


    接下来是实现 

    package com.oa.service.impl;  
      
    import com.oa.User;  
    import com.oa.dao. UserDao;  
    import com.oa.service.TestUserService;  
      
    public class UserService implements UserService {  
      
        private  UserDao  UserDao;  
        public void save(User user) {  
            UserDao.save(user);  
      
        }  
      
        public void updasaveorupdatete(User user) {  
            UserDao.saveorupdate(user);  
      
        }  
      
        public int   login(User user) {  
            return   UserDao.login(user);  
      
        }  
      
    //其他的方法。。。。  
      
    }  

    Ok。。到现在我们就利用泛型dao来设计就完毕了 

    两者相对比,发现dao层的代码可以复用,少了不少。 

    对于大型管理系统,效果更明显。 

  • 相关阅读:
    Event-Driven Architecture思考
    Kafka分区分配策略分析——重点:StickyAssignor
    Ubiq:A Scalable and Fault-tolerant Log Processing Infrastructure
    11张PPT介绍Paxos协议
    译《The Part-Time Parliament》——终于读懂了Paxos协议!
    谈谈分布式系统的一致性
    Pulsar Consumer实现介绍
    Pulsar-Producer实现简介
    RocketMQ事务消息实现分析
    Apache Pulsar简介
  • 原文地址:https://www.cnblogs.com/dandan1224/p/6109271.html
Copyright © 2020-2023  润新知