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; } }
分析:
当前页与每页显示多少个,这两个属性是分页查询的一个指标。是我们动态传入的,所以这两个属性是不论怎么样的都要有的,而多条件查询的条件们是不确定的,我们需要让用户去动态的增加查询条件。所以我们把这些所需的分页属性封装在一起。
(二) 查询通用接口
public abstract class BaseQuery { public Integer currentPage; public Integer pageSize; public Map<String, Object> keyValues; public abstract Map<String, Object> someCondition(); getter and setter.. }
(三) 通用接口实现类
@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; }
(四) 通用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; }
(五) 使用
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()); }