Hibernate反射DAO模式

Stella981
• 阅读 761

在持久层框架中,如果我们要像简单的JDBC连接数据库那样写一个通用的Dao方法的话,那么把JDBC简单的业务逻辑搬到hibernate持久层框架中,当然是不可能的,这里主要的问题就在于hibernate持久层框架中,因为它不是像JDBC那样简单的增删改查的编写,而是要针对实体类映射配置文件来对照数据库表字段进行操作,而且操作是面向对象的查询,不是简单的sql语句的查询,这样我们的通用DAO模式就不能是简单的JDBC思路了。

试想,项目底层的通用DAO接口方法,是适用于所有实体类对象应用的,而且数据库读取的所有实体类集合也是一个通用的类模型。这样,和简单的JDBC模式不同的基础上,hibernate通用的DAO模型,就需要我们利用反射序列化的技术机制来完成。因此无论是插入的类对象和读取的类模型信息,通过反射序列化来获取。具体的操作流程如下:

首先,在我们的通用DAO接口中,体现出所有通用功能的方法名外,我们需要定义的另外一个技术,就是泛型类编程模式,我们需要给类加上类型,也就是给类加上泛型模式编程。另外,在泛型中,需要定义两个属性,1是给类加一个继承序列化的变量,和给主键ID继承的一个序列化。因此反射DAO接口如下:

public interfaceIGenericDao<T **extends** Serializable,ID **extends** Serializable>

另外,所有的功能方法名,随之也会有所更改,例如我们添加一条信息时候,之前的参数是需要具体的实体类对象,而现在则是泛型的属性为实体类的对象,如下:

public T create(T entity);返回值也是一样。

因此在通用DAO接口如图:Hibernate反射DAO模式

具体的类实现中,除了实现该通用的DAO接口外,还需要自身的泛型编程和继承HibernateDaoSupport父类,因此实现类的方法名为:

public classGenericHibernateDao<T **extends**Serializable,ID **extends** Serializable> extends HibernateDaoSupport implements
IGenericDao<T, ID>。

因此例如在插入数据时候实现类代码则是:

@Override

public T create(T entity) {

return (T) this.getHibernateTemplate().save(entity);

}

这里反射序列化的类对象T,作为通用Dao接口的实现类实体类通用类型,但是在实现类的查询中,也就是读取中,我们也需要获取一个反射序列化的通过实体类对象模型,这就是需要反射的Class实例对象了,因此在通用DAO接口的实现类中,我们需要创建一个Class实例对象,这个对象中我们需要的泛型类型是反射序列化的实体类对象模型T,因此这个对象为

Class persistentClass;

但是我们还需要这个Class实例对象来获取反射序列化的具体对象模型,这就需要我们通过java底层对象类型来获取了,具体为

this.persistentClass=

(Class)(ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];

这里面1. getClass().getGenericSuperclass():获取java最底层类对象

  1. (ParameterizedType)getClass().getGenericSuperclass()):转换为可序列化类型

  2. .getActualTypeArguments()[0] 反射出第一个参数对象信息,也就是获取类泛型中T extends Serializable

  3. (Class):强转为当前类对象

通过这些复杂的过程,我们可以获取反射序列化的具体Class实例类型,这样就可以通过该Class实例来获取具体查询的结果集合。

因此实现类的代码大致如下:

public class GenericHibernateDao<T **extends** Serializable,ID **extends** Serializable>

extendsHibernateDaoSupport implements
IGenericDao<T, ID> {

Class persistentClass;

public GenericHibernateDao() {

// 强转为当前类对象,转换为可序列化类型, 获取java最底层类对象 反射出第一个参数对象信息

this.persistentClass=(Class) ((ParameterizedType)getClass().getGenericSuperclass()).getActualTypeArguments()[0];

}

public Class getPersistentClass() {

return persistentClass;

}

public void setPersistentClass(Class persistentClass) {

this.persistentClass = persistentClass;

}

@Override

public T create(T entity) {

return (T) this.getHibernateTemplate().save(entity);

}

@Override

public void delete(ID id) {

//删除通用方法 参数为要删除的实体类对象

System.out.println("IDD "+id);

this.getHibernateTemplate().delete(this.findById(id));

}

@Override

public void update(T entity) {

this.getHibernateTemplate().update(entity);

}

@Override

public T findById(ID id) {

return this.getHibernateTemplate().get(persistentClass, id);

}

@Override

public List findAll() {

return this.getHibernateTemplate().loadAll(persistentClass);

}

@Override

public List findByObject(String hql, Object[] param) {

return this.getHibernateTemplate().find(hql, param);

}

@Override

public PageBean findByPageBean(final String hql,final Object[] param,final int currentpage,final int pageSize) {

return this.getHibernateTemplate().execute(new
HibernateCallback() {

@Override

public PageBean doInHibernate(Session session)throws
HibernateException, SQLException {

//创建pagebean对象

PageBean pb=new PageBean();

//通过Query对象来获取所需要页的数据

Query qu=session.createQuery(hql);

//赋值参数

if(param.length>0){

for (int i = 0; i < param.length; i++) {

qu.setParameter(i, param[i]);

}

}

//为Query对象,赋值从第几行到第几行参数,也就是最大最小页数值

qu.setFirstResult((currentpage-1)*pageSize);

qu.setMaxResults(pageSize);

//给PageBean对象,赋值list参数

pb.setData(qu.list());

//获取总行数

qu=session.createQuery("select count(*) "+hql.substring(hql.toLowerCase().indexOf("from")));

//赋值获取总行数参数

if(param.length>0){

for (int j = 0; j <
param.length; j++) { qu.setParameter(j, param[j]);

}

}

//Pagebean赋值总行数参数

pb.setTotalRows(Integer.parseInt(qu.uniqueResult().toString()));

//Pagebean赋值当前页参数

pb.setCurrentPage(currentpage);

//Pagebean赋值每页大小参数

pb.setPageSize(pageSize);

//返回pagebean对象

return pb;

}

});

}

@Override

public void bulkUpdate(String bulk, Object[] param) {

this.getHibernateTemplate().bulkUpdate(bulk,param);

}

@Override

public Integer countByObject(final String hql,final Object[] param) {

return this.getHibernateTemplate().execute(new
HibernateCallback() {

//获取hibernateSessionFactory接口方法

@Override

public Integer doInHibernate(Session session)throws
HibernateException, SQLException {

//通过HIbernateQuery方法来获取count值

Query qu=session.createQuery(hql);

for (int i = 0; i < param.length; i++) {

qu.setParameter(i, param[i]);

}

return Integer.parseInt(qu.uniqueResult().toString());

}

});

}

}

以上是反射DAO模式的实现类及接口的核心代码,通过具体的实体类对象来获取具体的类对象集合,就可以实现具体的通过DAO反射序列化的接口及实现类的效果。

作者:中软卓越天津ETC

点赞
收藏
评论区
推荐文章
blmius blmius
3年前
MySQL:[Err] 1292 - Incorrect datetime value: ‘0000-00-00 00:00:00‘ for column ‘CREATE_TIME‘ at row 1
文章目录问题用navicat导入数据时,报错:原因这是因为当前的MySQL不支持datetime为0的情况。解决修改sql\mode:sql\mode:SQLMode定义了MySQL应支持的SQL语法、数据校验等,这样可以更容易地在不同的环境中使用MySQL。全局s
皕杰报表之UUID
​在我们用皕杰报表工具设计填报报表时,如何在新增行里自动增加id呢?能新增整数排序id吗?目前可以在新增行里自动增加id,但只能用uuid函数增加UUID编码,不能新增整数排序id。uuid函数说明:获取一个UUID,可以在填报表中用来创建数据ID语法:uuid()或uuid(sep)参数说明:sep布尔值,生成的uuid中是否包含分隔符'',缺省为
Jacquelyn38 Jacquelyn38
3年前
2020年前端实用代码段,为你的工作保驾护航
有空的时候,自己总结了几个代码段,在开发中也经常使用,谢谢。1、使用解构获取json数据let jsonData  id: 1,status: "OK",data: 'a', 'b';let  id, status, data: number   jsonData;console.log(id, status, number )
待兔 待兔
2个月前
手写Java HashMap源码
HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程HashMap的使用教程22
Wesley13 Wesley13
2年前
mysql设置时区
mysql设置时区mysql\_query("SETtime\_zone'8:00'")ordie('时区设置失败,请联系管理员!');中国在东8区所以加8方法二:selectcount(user\_id)asdevice,CONVERT\_TZ(FROM\_UNIXTIME(reg\_time),'08:00','0
Wesley13 Wesley13
2年前
00:Java简单了解
浅谈Java之概述Java是SUN(StanfordUniversityNetwork),斯坦福大学网络公司)1995年推出的一门高级编程语言。Java是一种面向Internet的编程语言。随着Java技术在web方面的不断成熟,已经成为Web应用程序的首选开发语言。Java是简单易学,完全面向对象,安全可靠,与平台无关的编程语言。
Stella981 Stella981
2年前
Django中Admin中的一些参数配置
设置在列表中显示的字段,id为django模型默认的主键list_display('id','name','sex','profession','email','qq','phone','status','create_time')设置在列表可编辑字段list_editable
Wesley13 Wesley13
2年前
MySQL部分从库上面因为大量的临时表tmp_table造成慢查询
背景描述Time:20190124T00:08:14.70572408:00User@Host:@Id:Schema:sentrymetaLast_errno:0Killed:0Query_time:0.315758Lock_
为什么mysql不推荐使用雪花ID作为主键
作者:毛辰飞背景在mysql中设计表的时候,mysql官方推荐不要使用uuid或者不连续不重复的雪花id(long形且唯一),而是推荐连续自增的主键id,官方的推荐是auto_increment,那么为什么不建议采用uuid,使用uuid究
Python进阶者 Python进阶者
8个月前
Excel中这日期老是出来00:00:00,怎么用Pandas把这个去除
大家好,我是皮皮。一、前言前几天在Python白银交流群【上海新年人】问了一个Pandas数据筛选的问题。问题如下:这日期老是出来00:00:00,怎么把这个去除。二、实现过程后来【论草莓如何成为冻干莓】给了一个思路和代码如下:pd.toexcel之前把这