• 调查管理系统 -(4)DAO与Service层的泛型抽取与实现


    1、设计 BaseDao 与 BaseDaoImpl

    1)设计接口 BaseDao

    每个实体都应有一个对应的Dao接口,封装了对这个实体的数据库操作。在每个Dao接口中都应有一个基本的增删改查的方法,但每个Dao接口中都写一遍就是重复的代码,可以把这些方法抽取到一个父接口中,定义为:

     1 package com.atguigu.surveypark.dao;
     2 import java.util.List;
     3 /**
     4  * BaseDao接口
     5  */
     6 public interface BaseDao<T> {
     7     //写操作
     8     public void saveEntity(T t);
     9     public void saveOrUpdateEntity(T t);
    10     public void updateEntity(T t);
    11     public void deleteEntity(T t);
    12     public void batchEntityByHQL(String hql,Object...objects); //按照HQL语句进行批量更新
    13     //执行原生的sql语句
    14     public void executeSQL(String sql,Object...objects);
    15     
    16     //读操作
    17     public T loadEntity(Integer id);
    18     public T getEntity(Integer id);
    19     public List<T> findEntityByHQL(String hql,Object...objects);
    20     //单值检索,确保查询结果有且只有一条记录
    21     public Object uniqueResult(String hql,Object...objects);
    22     //执行原生的sql查询(可以指定是否封装成实体)
    23     public List executeSQLQuery(Class clazz,String sql,Object...objects);
    24 }

    2)设计实现类 BaseDaoImpl

    每个Dao的接口还要有相应的实现类才可以,在每个DaoImpl中都要实现Dao接口中定义的所有方法,当然也包括公共的增删改查方法(BaseDao中定义的基本方法)。每个DaoImpl中都实现一遍公共方法显示是重复的,所以也可以抽取出来为一个父类BaseDaoImpl,在BaseDaoImpl中实现了BaseDao接口的所有方法,我们的DaoImpl只需要继承他就可以不用重复的写公共方法的实现了。
    声明如下:

     1 package com.atguigu.surveypark.dao.impl;
     2 import java.lang.reflect.ParameterizedType;
     3 import java.util.List;
     4 import javax.annotation.Resource;
     5 import org.hibernate.SessionFactory;
     6 import com.atguigu.surveypark.dao.BaseDao;
     7 /**
     8  * 抽象的dao实现,专门用于继承
     9  */
    10 @SuppressWarnings("unchecked")
    11 public abstract class BaseDaoImpl<T> implements BaseDao<T> {
    12     @Resource
    13     private SessionFactory sessionFactory ; // 让Spring注入sessionFactory
    14     private Class<T> clazz ;
    15     public BaseDaoImpl(){
    16         //得到泛型化超类(返回值为参数化类型)
    17         ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();
    18         clazz = (Class<T>) type.getActualTypeArguments()[0];
    19     }
    20     
    21     protected Session getSession() { //获取Session
    22         return sessionFactory.getCurrentSession();
    23     }
    24     //省略了对接口中方法的实现
    25 }

    这里用到了泛型技术,需要在程序执行过程中确定泛型T的具体类型clazz获取clazz时有两种方法:

    方法一:

    Ⅰ、把clazz声明成protected修饰符的,这样子类中就可以访问了,
    Ⅱ、在每个子类的构造方法中传递这个属性的值,如:
      public RoleDaoImpl() { clazz = Role.class; }
      public UserDaoImpl() { clazz = User.class; }

    方法二:使用反射的方式(即上述BaseDaoImpl中使用的方法):

    Ⅰ、在BaseDaoImpl的默认构造方法中写如下代码就可以了:
      ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
      clazz = (Class) pt.getActualTypeArguments()[0];
    Ⅱ、说明:即使BaseDaoImpl没有被定义为抽象类也不能直接使用,只能使用他的子类,否则这段代码就无效了。因为只能通过其子类指定了泛型的具体类型之后,才能够在BaseDaoImpl的构造方法中获取到clazz的具体类型。

    2、设计 BaseService 与 BaseServiceImpl

    1)设计接口BaseService

    在设计BaseService时有个不成文的规定,就是将BaseDao中的基本方法全部都复制到BaseServic中即可,如有需要扩展的业务方法则再独立设计相应的Service接口,然后继承BaseService接口即可。

    因此BaseService的定义如下:

     1 package com.atguigu.surveypark.service;
     2 import java.util.List;
     3 /**
     4  * 基本的Service接口
     5  */
     6 public interface BaseService<T> {
     7     //写操作
     8     public void saveEntity(T t);
     9     public void saveOrUpdateEntity(T t);
    10     public void updateEntity(T t);
    11     public void deleteEntity(T t);
    12     public void batchEntityByHQL(String hql,Object...objects);
    13     //执行原生的sql语句
    14     public void executeSQL(String sql,Object...objects);
    15     
    16     //读操作
    17     public T loadEntity(Integer id);
    18     public T getEntity(Integer id);
    19     public List<T> findEntityByHQL(String hql,Object...objects);
    20     //单值检索,确保查询结果有且只有一条记录
    21     public Object uniqueResult(String hql,Object...objects);
    22     //查询所有实体
    23     public List<T> findAllEntities();
    24     public List executeSQLQuery(Class clazz,String sql,Object...objects);
    25 }

    2)设计实现类 BaseServiceImp

    在BaseServiceImpl中同样采用了泛型技术,方便程序的实现。在BaseServiceImpl中主要是通过Spring注入了dao,然后通过dao调用了BaseDaoImpl中的基本方法的实现,已完成基本的业务操作。

    具体实现如下:

     1 package com.atguigu.surveypark.service.impl;
     2 import java.lang.reflect.ParameterizedType;
     3 import java.util.List;
     4 import javax.annotation.Resource;
     5 import com.atguigu.surveypark.dao.BaseDao;
     6 import com.atguigu.surveypark.service.BaseService;
     7 /**
     8  * 抽象的Service实现,专门用于继承
     9  */
    10 public abstract class BaseServiceImpl<T> implements BaseService<T> {
    11     private BaseDao<T> dao ;
    12     private Class<T> clazz ;
    13     @SuppressWarnings("unchecked")
    14     public BaseServiceImpl() {
    15         ParameterizedType type = (ParameterizedType) this.getClass().getGenericSuperclass();
    16         clazz = (Class<T>) type.getActualTypeArguments()[0];
    17     }
    18     @Resource //注入dao
    19     public void setDao(BaseDao<T> dao) {
    20         this.dao = dao;
    21     }
    22     //省略了对接口中方法的实现
    23 }

    注意:在这里注入的是BaseDao接口的实现类,并且注解@Resource是添加在setDao方法上的。这是因为,BaseDao有多个实现类,因此在Spring进行dao注入时会有多个匹配的BaseDao的实现类满足条件,因此不能将@Resource注解添加在属性上,而是添加到set方法上,这样,具体的Service实现类中可以覆写setDao方法,在@Resource注解中添加name属性指定要注入的具体的Dao实现类。如下所示:

     1 //UserService接口
     2 public interface UserService extends BaseService<User> {}
     3 //UserServiceImpl实现类
     4 @Service("userService")
     5 public class UserServiceImpl extends BaseServiceImpl<User> implements UserService {
     6     /**
     7      * 重写该方法,目的是为了覆盖超类中该方法的注解,指明注入指定的Dao对象,否则spring
     8      * 无法确定注入哪个Dao---有多个满足条件的Dao.
     9      */
    10     @Resource(name="userDao")
    11     public void setDao(BaseDao<User> dao) {
    12         super.setDao(dao);
    13     }
    14 }         
  • 相关阅读:
    DedeCMS系统301重定向配置方法详解
    dedecms批量更新静态时提示:没有该栏目数据 可能缓存的解决方法
    修改织梦dedecms后台默认admin账号的方法
    织梦DeDeCMS动态热点文章排行调用方法
    文件与字符串处理时常见的问题(中文英文)
    基于OpenCV全景拼接(Python)SIFT/SURF
    解决关闭ssh后网页停止服务的方法,利用nohup
    解决宝塔面板没有命令行问题 && 查看宝塔面板项目环境
    python 正则表达式
    JAVAC 不是内部或外部命令
  • 原文地址:https://www.cnblogs.com/KnightKitt/p/3951812.html
Copyright © 2020-2023  润新知