zoukankan      html  css  js  c++  java
  • 调查管理系统 -(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 }         
  • 相关阅读:
    欧拉回路 定理
    UESTC 1087 【二分查找】
    POJ 3159 【朴素的差分约束】
    ZOJ 1232 【灵活运用FLOYD】 【图DP】
    POJ 3013 【需要一点点思维...】【乘法分配率】
    POJ 2502 【思维是朴素的最短路 卡输入和建图】
    POJ 2240 【这题貌似可以直接FLOYD 屌丝用SPFA通过枚举找正权值环 顺便学了下map】
    POJ 1860【求解是否存在权值为正的环 屌丝做的第一道权值需要计算的题 想喊一声SPFA万岁】
    POJ 1797 【一种叫做最大生成树的很有趣的贪心】【也可以用dij的变形思想~】
    js 实现slider封装
  • 原文地址:https://www.cnblogs.com/KnightKitt/p/3951812.html
Copyright © 2011-2022 走看看