(project)利用接口,继承,泛型封装dao数据访问层
2015-12-05 14:51
495 查看
一般在建立工程的时候会根据不同的模块的功能来建包,
dao层的代码是用来访问数据库的,它通过操作domain领域层的对象,对数据库进行增删改查的操作。
但是,一般情况下,一个项目有多个表,对应到面向对象的语言就会相应的要创建多个类对象。进而根据对应的对象创建dao层的类,比如,有一个Person对象,如果要操作该对象的话,相应的就要创建PersonDaoImpl这个类来操作person这个对象,对它进行增删改查的操作,就要实现增删改查的代码。但是如果有十个,二十个对象,对应的要创建十个,二十个dao类,同时实现增删改查的代码,那么这样问题就来了,这些代码其实都是有相似的地方的,就是增删改查的代码都是一样的,只不过要操作的对象不一样吧了。
所以我们考虑到可以使用继承,接口的思想来实现代码的重用,抽出一个父类,ICommonDao是一个接口,CommonDaoImpl是该接口的实现。但是,是否要利用Object来指向所有的对象呢,其实这里我们使用的是泛型的技术来实现。
下面是给出的代码
上面定义一个公共的访问数据层的接口,已经抽取出公有的方法。
下面会定义一个类来实现这个接口。
public class CommonDaoImpl extends HibernateDaoSupport implements ICommonDao {
}
上面的类中有一个行代码是很重要的
通过一个工具类GenericSuperClass调用getActualTypeClass方法来获取真实的T泛型类型。
只要继承这个类并传入泛型类型,最后得到的entityClass对象就是传入的泛型的对象。
//通过依赖注入SessionFactory类,获取hibernateTempalte对象
@Resource(name=”sessionFactory”)
public final void setSessionFactoryDI(SessionFactory sessionFactory){
super.setSessionFactory(sessionFactory);
}
因为CommonDaoImpl继承了HibernateDaoSupport这个类,所以可以使用这个类的对象方法this.getHibernateTemplate();获取得到hibernate的模板,这是Spring框架提供的。但是,一定要给这个类的属性赋值,所以要使用上面的代码,依赖注入sessionFactory,而这个sessionFactory在spring配置文件里已经定义了。所以在部署启动服务器的时候就会初始化这个sessionFactory然后赋值给给这个属性。
这里的工作已经做的差不多了,后面实现各个对象的访问层类的编写就很容易多了。
从上面的代码可以看出,UserDaoImpl里面什么代码都不用写,因为他已经继承了CommonDaoImpl这个类,并通过泛型User传递进去,所以,直接调用父类的增删改查的方法就可以对数据库中User表的数据进行操作。
dao层的代码是用来访问数据库的,它通过操作domain领域层的对象,对数据库进行增删改查的操作。
但是,一般情况下,一个项目有多个表,对应到面向对象的语言就会相应的要创建多个类对象。进而根据对应的对象创建dao层的类,比如,有一个Person对象,如果要操作该对象的话,相应的就要创建PersonDaoImpl这个类来操作person这个对象,对它进行增删改查的操作,就要实现增删改查的代码。但是如果有十个,二十个对象,对应的要创建十个,二十个dao类,同时实现增删改查的代码,那么这样问题就来了,这些代码其实都是有相似的地方的,就是增删改查的代码都是一样的,只不过要操作的对象不一样吧了。
所以我们考虑到可以使用继承,接口的思想来实现代码的重用,抽出一个父类,ICommonDao是一个接口,CommonDaoImpl是该接口的实现。但是,是否要利用Object来指向所有的对象呢,其实这里我们使用的是泛型的技术来实现。
下面是给出的代码
public interface ICommonDao<T> { /** * <p>保存一条数据 </p> */ void save(T entity); /** * * <p>保存多条数据 </p> */ void saveConllection(Collection<T> entities); /** * <p>删除一条数据 </p> */ void deleteById(Serializable id); /** * <p>根据id数组删除多条数据 </p> */ void deleteByIds(Collection<T> entities); /** * <p>更新一条数据 </p> */ void update(T entity); /** * <p>更新一条数据 </p> */ void partialRenewal(List<Object>keys,List<Object>params ,LinkedHashMap<String,Object> conditions); /** * <p>根据id查看一条数据 </p> */ T findEntityById(Serializable id); /** * <p>根据id数组查找多条数据 </p><br/> * <P>由于数据库里面的实体是不能够重复的,所以这里使用Set集合</p> */ Set<T> findEntitiesByIds(Serializable ... ids); /** * * <p>查找所有对象</p> */ Collection<T> findAll(); /** * *<p>根据多个条件查询数据</p> */ List<T> findCollectionByConditionNoPage(String condition, Object[] params, LinkedHashMap<String, String> hashMap); /** * *<p>根据多个条件查询数据,并且使用了二级缓存</p> */ List<T> findCollectionByConditionNoPageWithCache(String condition, Object[] params, LinkedHashMap<String, String> hashMap); }
上面定义一个公共的访问数据层的接口,已经抽取出公有的方法。
下面会定义一个类来实现这个接口。
public class CommonDaoImpl extends HibernateDaoSupport implements ICommonDao {
@SuppressWarnings("rawtypes") private Class entityClass = GenericSuperClass.getActualTypeClass(this.getClass()) ; //通过依赖注入SessionFactory类,获取hibernateTempalte对象 @Resource(name="sessionFactory") public final void setSessionFactoryDI(SessionFactory sessionFactory){ super.setSessionFactory(sessionFactory); } /** * @Name: save * @Description: 保存 * @Author: 张淼洁(作者) * @Version: V1.00 (版本号) * @Create Date: 2015-06-20 (创建日期) * @Param T entity 保存对象 */ public void save(T entity) { this.getHibernateTemplate().save(entity); } /** * @Name: deleteById * @Description: 根据实体的id删除数据 * @Author: 张淼洁(作者) * @Version: V1.00 (版本号) * @Create Date: 2015-06-20 (创建日期) * @Param Serializable id 实体的id字段 */ public void deleteById(Serializable id) { T entity = findEntityById(id); this.getHibernateTemplate().delete(entity); } /** * @Name: deleteByIds * @Description: 根据实体的id删除数据 * @Author: 张淼洁(作者) * @Version: V1.00 (版本号) * @Create Date: 2015-06-20 (创建日期) * @Param Serializable id 实体的id字段 */ public void deleteByIds(Collection<T> entities) { this.getHibernateTemplate().deleteAll(entities); } public void update(T entity) { this.getHibernateTemplate().update(entity); } @SuppressWarnings("unchecked") public T findEntityById(Serializable id) { return (T) this.getHibernateTemplate().get(entityClass, id); } @SuppressWarnings("unchecked") public Set<T> findEntitiesByIds(Serializable... ids) { Set<T> set = new HashSet<T>(); for(int id=0; id<ids.length; id++){ set.add((T)this.getHibernateTemplate().get(entityClass, ids[id])); } return set; } @SuppressWarnings("unchecked") public Collection<T> findAll() { return this.getHibernateTemplate().find("from " + entityClass.getName()); } /**根据条件进行模糊查询*/ @SuppressWarnings("rawtypes") @Override public List<T> findCollectionByConditionNoPage(String condition, final Object[] params, LinkedHashMap<String, String> hashMap) { /* * web界面查询用户的信息,where默认为1=1,这样用户即使不选择任何条件,sql查询也不会出错。 */ String hql = "from "+entityClass.getSimpleName() +" o where 1=1"; String orderby = ""; //判断是否需要排序 if(hashMap !=null){ orderby = orderByHql(hashMap); } //from SystemGroupUser o where 1=1 and o.name like ? and o.principal = ? order by o.id desc final String finalHql = hql + condition + orderby; System.out.println("hql : "+hql); @SuppressWarnings({ "unchecked" }) List<T> list = (List<T>) this.getHibernateTemplate().execute(new HibernateCallback() { @Override public Object doInHibernate(Session session) throws HibernateException, SQLException { Query query = session.createQuery(finalHql); for(int i=0;params!=null && i<params.length;i++){ query.setParameter(i, params[i]); } return query.list(); } }); return list; } /**通过传递的排序集合语句(Map),获取对应的排序条件(String)*/ /**ORDER BY o.textDate ASC,o.textName DESC*/ private String orderByHql(LinkedHashMap<String, String> hashMap) { StringBuffer order = new StringBuffer(""); if(hashMap != null && !hashMap.isEmpty()){ order.append(" order by "); for(Map.Entry<String, String> map : hashMap.entrySet()){ order.append(map.getKey()+" "+map.getValue()+" ,"); } order.deleteCharAt(order.length()-1);//去掉最后一个逗号 } return order.toString(); } /** * @Name: partialRenewal * @Description: 根据业务层传递的条件和要更新的字段进行局部的更新 * @Auth 4000 or: 张淼洁(作者) * @Version: V1.00 (版本号) * @Create Date: 2015-06-20 (创建日期) * @Param params 要更新的字段 * condition 条件 */ @Override public void partialRenewal(List<Object>keys,List<Object>params ,LinkedHashMap<String,Object> conditions) { //字段和实际的值数量要一致 if(keys.size()!=params.size()){ throw new RuntimeException("字段的数量和更新的值的数量不一致!"); } //将集合对象转换为数组对象 Object[]keyArray = keys.toArray(); Object[]paramArray = params.toArray(); HibernateUtil hibernateUtil = HibernateUtil.getHibernateUtil(); Session session = HibernateUtil.getSession(); //定义查询的语句 /*String hql = "update "+getTableName4ClassName()+" set ";*/ String hql = "update "+ hibernateUtil.getTableName4ClassName(entityClass)+" set "; //组织查询语句的关键字段 for(int i=0; i<keys.size(); i++){ if(i==0){ hql += ""+keyArray[i]+"= "+modifiedField(paramArray[i]) +""; }else{ hql +=","+keyArray[i]+"= "+modifiedField(paramArray[i]) +""; } } hql +=updateConditionByHql(conditions); final String executeSQL = hql; System.out.println("hql :"+hql); session.beginTransaction(); SQLQuery query = session.createSQLQuery(executeSQL); int result = query.executeUpdate(); System.out.println("一共有"+result+"条数据被影响!"); session.getTransaction().commit(); HibernateUtil.closeSession(session); /*return result; */ } /** * @description:判断表字段的类型,从而是否进行字段的修饰 * @param type * @return */ private String modifiedField(Object type){ if(type == null){ throw new RuntimeException("type 不能为空!"); } StringBuffer sb = new StringBuffer(); if(type instanceof String){ String stringType = (String)type; sb.append("'"); sb.append(stringType); sb.append("'"); return new String(sb); }else if(type instanceof Date){ String dateType =new SimpleDateFormat("yyyy-MM-dd").format(type); sb.append("'"); System.out.println("date ==" +dateType); sb.append(dateType); sb.append("'"); return new String(sb); } return type+""; } /** * @description 组织好更新的条件 * @param conditions * @return */ private String updateConditionByHql(LinkedHashMap<String,Object> conditions){ if(conditions == null || conditions.keySet().size()<=0){ throw new RuntimeException("更新条件不能为空!"); } StringBuffer sb = new StringBuffer(); sb.append(" where "); for(Map.Entry<String, Object> entry:conditions.entrySet()){ sb.append(" "+entry.getKey()+"="+modifiedField(entry.getValue())); } System.out.println("更新条件为 "+new String(sb)); return new String(sb); } @SuppressWarnings("rawtypes") @Override public List<T> findCollectionByConditionNoPageWithCache(String condition, final Object[] params, LinkedHashMap<String, String> hashMap) { /* * web界面查询用户的信息,where默认为1=1,这样用户即使不选择任何条件,sql查询也不会出错。 */ String hql = "from "+entityClass.getSimpleName() +" o where 1=1"; String orderby = ""; //判断是否需要排序 if(hashMap !=null){ orderby = orderByHql(hashMap); } //from SystemGroupUser o where 1=1 and o.name like ? and o.principal = ? order by o.id desc final String finalHql = hql + condition + orderby; System.out.println("hql : "+hql); @SuppressWarnings({ "unchecked" }) List<T> list = (List<T>) this.getHibernateTemplate().execute(new HibernateCallback() { @Override public Object doInHibernate(Session session) throws HibernateException, SQLException { Query query = session.createQuery(finalHql); for(int i=0;params!=null && i<params.length;i++){ query.setParameter(i, params[i]); } //启用二级缓存存储数据 query.setCacheable(true); return query.list(); } }); return list; } @Override public void saveConllection(Collection<T> entities) { this.getHibernateTemplate().saveOrUpdateAll(entities); }
}
上面的类中有一个行代码是很重要的
@SuppressWarnings("rawtypes") private Class entityClass = GenericSuperClass.getActualTypeClass(this.getClass()) ;
通过一个工具类GenericSuperClass调用getActualTypeClass方法来获取真实的T泛型类型。
public class GenericSuperClass { /** * * @param clazz * @return class对象 * @description 将泛型转换为class类对象 */ @SuppressWarnings("rawtypes") public static Class getActualTypeClass(Class clazz){ ParameterizedType type = (ParameterizedType) clazz.getGenericSuperclass(); Class entityClass = (Class) type.getActualTypeArguments()[0]; return entityClass; } }
只要继承这个类并传入泛型类型,最后得到的entityClass对象就是传入的泛型的对象。
//通过依赖注入SessionFactory类,获取hibernateTempalte对象
@Resource(name=”sessionFactory”)
public final void setSessionFactoryDI(SessionFactory sessionFactory){
super.setSessionFactory(sessionFactory);
}
因为CommonDaoImpl继承了HibernateDaoSupport这个类,所以可以使用这个类的对象方法this.getHibernateTemplate();获取得到hibernate的模板,这是Spring框架提供的。但是,一定要给这个类的属性赋值,所以要使用上面的代码,依赖注入sessionFactory,而这个sessionFactory在spring配置文件里已经定义了。所以在部署启动服务器的时候就会初始化这个sessionFactory然后赋值给给这个属性。
这里的工作已经做的差不多了,后面实现各个对象的访问层类的编写就很容易多了。
public interface IUserDao extends ICommonDao<User>{ public final static String SERVICE_NAME = "cn.water.cf.dao.impl.UserDaoImpl"; } @Repository(IUserDao.SERVICE_NAME) public class UserDaoImpl extends CommonDaoImpl<User> implements IUserDao{ }
从上面的代码可以看出,UserDaoImpl里面什么代码都不用写,因为他已经继承了CommonDaoImpl这个类,并通过泛型User传递进去,所以,直接调用父类的增删改查的方法就可以对数据库中User表的数据进行操作。
相关文章推荐
- JAVA泛型—— 3fe8 转
- JAVA泛型详解——转
- PostgreSQL教程(三):表的继承和分区表详解
- Lua编程示例(二):面向对象、metatable对表进行扩展
- C#中面向对象编程机制之多态学习笔记
- 浅谈Lua的面向对象特性
- Lua面向对象之类和继承浅析
- 浅析Ruby中继承和消息的相关知识
- JavaScript面向对象的两种书写方法以及差别
- 浅谈c# 面向对象之类与对象
- 编写高质量代码改善C#程序――使用泛型集合代替非泛型集合(建议20)
- C#面向对象特征的具体实现及作用详解
- C# 面向对象的基本原则
- C#通过反射创建自定义泛型
- 设计引导--一个鸭子游戏引发的设计理念(多态,继承,抽象,接口,策略者模式)
- 浅谈对c# 面向对象的理解
- C#泛型用法实例分析
- C语言泛型编程实例教程
- C++实现不能被继承的类实例分析
- Python3 面向对象概述