zoukankan      html  css  js  c++  java
  • Hibernate【DAO重构与高级分页】

    Hibernate重构DAO思路:

      第一步:实现通用DAO接口与实现类

        核心技术:

          (1)new 子类()的时候,子类会调用父类的构造函数,此时,父类便可以得知子类的信息

          (2)Hibernate的元数据,是描述持久化类数据的数据

      第二步:针对不同的表操作时,分别继承DAO实现类(为的是传递泛型),并不用做任何覆写

      第三步:操作什么表,调用什么Dao

    重构DAO实例:

      第一步:通用接口与实现

      接口:

    public interface CommonDao<T> {
        public List<T> getAllEntity();
        public Long getCount();
    }

      实现类:

    public class CommonDaoImpl<T> implements CommonDao<T> {
        private Class class1;
        private ClassMetadata classMetadata;
        public CommonDaoImpl() {
            ParameterizedType parameterizedType=(ParameterizedType)this.getClass().getGenericSuperclass();
            class1=(Class)parameterizedType.getActualTypeArguments()[0];
            classMetadata=HibernateUtils.sessionFactory.getClassMetadata(class1);
            
        }
        @Override
        public List<T> getAllEntity() {
            SessionFactory sessionFactory=HibernateUtils.getSessionFactory();
            Session session=sessionFactory.openSession();
            List<T> list=session.createQuery("from "+class1.getName()).list();
            session.close();
            return list;
        }

      第二步:针对不同的表操作,去继承通用实现类

    public class ClassesDao extends CommonDaoImpl<Classes> {}

      第三步:使用

            ClassesDao classesDao=new ClassesDao();
            System.out.println(classesDao.getAllEntity());

    Hibernate预编译

      要实现分页,必须要提一下预编译,因为我需要条件的拼接,在Hibernate中预编译有两种方式。

      方式一:

         Query query=session.createQuery("from domain.Student where name=?");
            query.setParameter(0,"王二狗");

      方式二:

            Query query=session.createQuery("from domain.Student where name=:name");
            query.setParameter("name","王二狗");

    Hibernate高级分页

      使用Hibernate高级分页,无非就是把查询条件如何写成通用的形式。难点在于怎么处理分页请求,并写出通用解决方案。

      

      用到的核心技术:抽象类的使用

    (一)  设计抽象数据类型(ADT)-分页类

      我们的分页都信息都在该类的实例里面

    public class PageResult<T> {
        private String url;    //需要设置的值
        private List<T> datas;    //从数据库获取的值
        /**
         * currentPage和pageSize是我们需要传入的数据,其他的数据可以通过计算获得
         */
        private int currentPage; //传递过来的值
        private int pageSize; //传递过来的值
        
        private int pageStartIndex; //构造函数中设置
        private int totalDatas; //传过来的
        private int totalPages;    //构造函数
        
        private int firstPage;
        private int lastPage;
        private int nextPage;
        private int prevPage;
        
        public PageResult(BaseQuery baseQuery,int totalDatas){
            this.currentPage=baseQuery.getCurrentPage();
            this.totalDatas=totalDatas;
            this.pageSize=baseQuery.getPageSize();
            totalPages=totalDatas%pageSize==0?totalDatas/pageSize:totalDatas/pageSize+1;
            pageStartIndex=(currentPage-1)*pageSize;
            
            /**
             * 使当前页始终在页码的中间,
             */
            if(totalPages>3){//这里的3是说,每页有几个索引
                firstPage=currentPage-1;
                lastPage=currentPage+1;
                if(firstPage<1){
                    firstPage=1;
                    lastPage=3;
                }
                if(lastPage>totalPages){
                    firstPage=totalPages-2;
                    lastPage=totalPages;
                }
            }else{
                firstPage=1;
                lastPage=totalPages;
            }
        }
    PageResult

      分析:

        当前页与每页显示多少个,这两个属性是分页查询的一个指标。是我们动态传入的,所以这两个属性是不论怎么样的都要有的,而多条件查询的条件们是不确定的,我们需要让用户去动态的增加查询条件。所以我们把这些所需的分页属性封装在一起。

    (二) 查询通用接口

    public abstract class BaseQuery {
        public Integer currentPage;
        public Integer pageSize;
        public Map<String, Object> keyValues;
        public abstract Map<String, Object> someCondition();
            getter and setter..
    }
    View Code

    (三) 通用接口实现类

        @Override
        public PageResult<T> getPageData(BaseQuery baseQuery) {
            SessionFactory sessionFactory=HibernateUtils.getSessionFactory();
            Session session=sessionFactory.openSession();
            //计算总页数
            Long nums=(Long)session.createQuery("select count("+classMetadata.getIdentifierPropertyName()+") from "+class1.getName()).uniqueResult();
            //PageResult需要两个参数,内部完成了一系列计算
            PageResult<T> pageResult=new PageResult<T>(baseQuery, nums.intValue());
            //拼接查询条件
            StringBuffer stringBuffer=new StringBuffer();
            stringBuffer.append("from "+class1.getName());
            stringBuffer.append(" where 1=1 ");
            for(Map.Entry<String, Object> entry:baseQuery.someCondition().entrySet()){
                stringBuffer.append("and "+entry.getKey()+"=:"+entry.getKey()+" ");
            }
            System.out.println("拼接的sql语句为:"+stringBuffer);
            
            Query query=session.createQuery(stringBuffer.toString());
            for(Map.Entry<String, Object> entry:baseQuery.someCondition().entrySet()){
                query.setParameter(entry.getKey(), entry.getValue());
            }
            query.setMaxResults(pageResult.getPageSize());
            query.setFirstResult(pageResult.getPageStartIndex());
            List<T> lists=query.list();
            pageResult.setDatas(lists);
            return pageResult;
        }
    View Code

    (四) 通用DAO

        @Override
        public PageResult<T> getPageData(BaseQuery baseQuery) {
            SessionFactory sessionFactory=HibernateUtils.getSessionFactory();
            Session session=sessionFactory.openSession();
            //计算总页数
            Long nums=(Long)session.createQuery("select count("+classMetadata.getIdentifierPropertyName()+") from "+class1.getName()).uniqueResult();
            //PageResult需要两个参数,内部完成了一系列计算
            PageResult<T> pageResult=new PageResult<T>(baseQuery, nums.intValue());
            //拼接查询条件
            StringBuffer stringBuffer=new StringBuffer();
            stringBuffer.append("from "+class1.getName());
            stringBuffer.append(" where 1=1 ");
            for(Map.Entry<String, Object> entry:baseQuery.getKeyValues().entrySet()){
                stringBuffer.append("and "+entry.getKey()+"=:"+entry.getKey()+" ");
            }
            System.out.println("拼接的sql语句为:"+stringBuffer);
            
            Query query=session.createQuery(stringBuffer.toString());
            for(Map.Entry<String, Object> entry:baseQuery.getKeyValues().entrySet()){
                query.setParameter(entry.getKey(), entry.getValue());
            }
            query.setMaxResults(pageResult.getPageSize());
            query.setFirstResult(pageResult.getPageStartIndex());
            List<T> lists=query.list();
            pageResult.setDatas(lists);
            return pageResult;
        }
    View Code

    (五)   使用

    StudentDao studentDao=new StudentDao();
            
            StudentQuery studentQuery=new StudentQuery();
            studentQuery.setName("小花");
            
            studentQuery.setCurrentPage(2);
            studentQuery.setPageSize(2);
        
            PageResult<Student> pageResult=studentDao.getPageData(studentQuery);
            List<Student> students=pageResult.getDatas();
            for(Student s:students){
                System.out.println(s.getId());
            }
    View Code
  • 相关阅读:
    Ubuntu 16 安装redis客户端
    crontab 参数详解
    PHP模拟登录发送闪存
    Nginx配置端口访问的网站
    Linux 增加对外开放的端口
    Linux 实用指令之查看端口开启情况
    无敌的极路由
    不同的域名可以指向同一个项目
    MISCONF Redis is configured to save RDB snapshots, but is currently not able to persist on disk. Commands that may modify the data set are disabled. Please check Redis logs for details about the error
    Redis 创建多个端口
  • 原文地址:https://www.cnblogs.com/xingdongpai/p/5137512.html
Copyright © 2011-2022 走看看