(project)利用接口,继承,泛型封装dao数据访问层

6 篇文章 0 订阅
4 篇文章 0 订阅

一般在建立工程的时候会根据不同的模块的功能来建包,
这里写图片描述
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: 根据业务层传递的条件和要更新的字段进行局部的更新
* @Author: 张淼洁(作者)
* @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表的数据进行操作。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值