SSH实战OA 03:设计BaseDAo

来源:互联网 发布:哪个软件有天九牌游戏 编辑:程序博客网 时间:2024/06/05 19:15

上一节已经把项目的框架环境搭建起来了。并且做了简单的测试,这一节我们主要来设计Dao共用类的。在做这项工作之前我们先来看一个问题:在开发的过程中,我们发现DAO层的主要作用就是对数据库进行增删改查。例如有用户管理、部门管理、角色管理、文章管理这四个模块:

实体 Dao接口 实现类 User UserDao UserDaoImpl Role RoleDao RoleDaoImpl Department DepartmentDao DepartmentDaoImpl Article ArticleDao ArticleDaoImpl

他们各自具有方法如下:

实体 Dao 方法 User UserDao save(User user), update(), delete(), find() Role RoleDao save(Role role), update(), delete(), find() Student StudentDao save(Student student), update(), delete(), find()

这四个Dao类的主要作用是对数据中相对应的表进行增删改查操作,这时候为了避免重复操作,可以将他们的基本操作方法提取出来作为一个基础类的共有方法。

类 方法 BaseDao save(T t), update(), delete(), find()

类的模型如图:
这里写图片描述
基于Java的单继承多现实原理,我们可以设计一个通用的BaseDao接口,他包含了save(),delete(),updae(),getById(),getByIds(),findAll()等共用的方法,这个Dao有一个基本的实现类BaseDaoImpl,对这个共用接口所有的方法实现。User对应的dao实现类可以继承BaseDaoImpl也同时实现了UserDao接口,Role对应的Dao实现类可以也可以继承BaseDaoImpl同时可以实现了RoleDao的接口。共用的方法放在BaseDao接口里面,实体对应的个体的独特方法放在自己的接口里面,这样便减少重复工作量!

BaseDao:

import java.util.List;/** * 泛型接口 * @author shizongger * @param <T> */public interface BaseDao<T> {    public void add(T entity);    public void delete(Long id);    public void update(T entity);    public T selectById(Long id);    public List<T> selectAll();}

BaseDaoImpl:

import java.lang.reflect.ParameterizedType;import java.util.List;import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.springframework.beans.factory.annotation.Autowired;import com.shizongger.oa.domain.User;/** * @author shizongger * @param <T> 实际操作的daomain实体 */public abstract class BaseDaoImpl<T> implements BaseDao<T> {    private Log log = LogFactory.getLog(this.getClass());       /**     * sessionFactory工厂     */    @Autowired    private SessionFactory sessionFactory;    private Class<T> clazz;    @SuppressWarnings("unchecked")    public BaseDaoImpl() {        // 使用反射技术得到T的真实类型        ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass(); // 获取当前new的对象的 泛型的父类 类型        this.clazz = (Class<T>) pt.getActualTypeArguments()[0]; // 获取第一个类型参数的真实类型    }    /**     * 增加     */    @Override    public void add(T entity) {        log.info("add:" + entity.toString());        getSession().save(entity);    }    /**     * 删除     */    @Override    public void delete(Long id) {        Object object = selectById(id);        if(object != null) {            getSession().delete(object);        }    }    /**     * 修改     */    @Override    public void update(T entity) {        getSession().update(entity);    }    /**     * 根据id查询     */    @Override    public T selectById(Long id) {        return (T) getSession().get(this.clazz, id);    }    /**     * 根据id数组查询     */    @Override    public List<T> selectAll() {        List<T> list = getSession().createQuery("FROM " + this.clazz.getSimpleName()).list();        return list;    }    protected Session getSession() {        return sessionFactory.getCurrentSession();    }}

由于共有类无法判断具体的实体,只能使用泛型,在调用过程中具体传递进来的实体类型是什么类型需要用java反射机制来实现。关键代码在我们的构造方法中的这两行代码:

// 使用反射技术得到T的真实类型ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass(); // 获取当前new的对象的 泛型的父类 类型this.clazz = (Class<T>) pt.getActualTypeArguments()[0]; // 获取第一个类型参数的真实类型

本类中多次用到hibernate的session,所以直接把获取session做成一个protected级别的方法。为了更好的给子类继承使用该方法,不宜写为private私有级别。

    protected Session getSession() {        return sessionFactory.getCurrentSession();    }

这里需要注意的是:基础实现类不能new,只能new他的子类,所以这里要写abstract抽象类型。

如此便可以在不同模块的Dao调用这个公共类了。
用户增删改查对应的UserDao接口

import com.shizongger.oa.base.BaseDao;import com.shizongger.oa.domain.User;public interface UserDao extends BaseDao<User> {    public User getUserByNamdAndPasswd(String username, String password);}

userDaoImpl实现类

import org.apache.commons.logging.Log;import org.apache.commons.logging.LogFactory;import org.hibernate.Session;import org.hibernate.SessionFactory;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.stereotype.Repository;import com.shizongger.oa.base.BaseDaoImpl;import com.shizongger.oa.dao.UserDao;import com.shizongger.oa.domain.User;@Repositorypublic class UserDaoImpl extends BaseDaoImpl<User> implements UserDao {    private Log log = LogFactory.getLog(this.getClass());       /**     * sessionFactory工厂     */    @Autowired    private SessionFactory sessionFactory;    /**     * 检测用户的合法性     */    @Override    public User getUserByNamdAndPasswd(String username, String password) {        Session session = sessionFactory.getCurrentSession();        String hql = "FROM User WHERE loginName = ? AND password = ?";        User user = (User) session.createQuery(hql).setString(0, username)                            .setString(1, password).uniqueResult();        return user;    }}

部门管理增删改查对应的接口DepartmentDao

import java.util.List;import com.shizongger.oa.base.BaseDao;import com.shizongger.oa.domain.Department;public interface DepartmentDao extends BaseDao<Department> {    List<Department> findTopDept();    List<Department> findChildren(String parentId);}

DepartmentDaoImpl实现类

import java.util.List;import com.shizongger.oa.base.BaseDao;import com.shizongger.oa.domain.Department;public interface DepartmentDao extends BaseDao<Department> {    List<Department> findTopDept();    List<Department> findChildren(String parentId);}

下面我们来进行junit测试:
BaseJunitTest

import org.junit.runner.RunWith;  import org.springframework.test.context.ContextConfiguration;  import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;  @RunWith(SpringJUnit4ClassRunner.class)    @ContextConfiguration(locations = {"classpath*:*.xml"})    public class BaseJunitTest {  }  

UserDaoImplTest

import static org.junit.Assert.*;import java.util.List;import org.junit.Ignore;import org.junit.Test;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.test.annotation.Rollback;import org.springframework.transaction.annotation.Transactional;import com.shizongger.oa.base.BaseJunitTest;import com.shizongger.oa.dao.UserDao;import com.shizongger.oa.domain.User;public class UserDaoImplTest extends BaseJunitTest {    @Autowired    private UserDao userDao;    @Test    @Ignore    public void testGetUserByNamdAndPasswd() throws Exception {        //TODO    }    @Transactional    @Test    @Rollback(false)    public void testAddUser() throws Exception {        User user = new User();        user.setName("shizongger");        userDao.add(user);    }    @Transactional    @Test    @Rollback(false)    public void testDelete() throws Exception {        userDao.delete(6L);    }    @Transactional    @Test    @Rollback(false)    public void testUpdate() throws Exception {        User user = (User) userDao.selectById(7L);        if(user != null) {            user.setName("admin");            userDao.update(user);        }    }    @Transactional    @Test    public void testSelectAll() throws Exception {        List<User> list = userDao.selectAll();        for(final User user : list) {            System.out.println("id:" + user.getId() + ", name:" + user.getName());        }    }}

我们发现调用到BaseDaoImpl的构造方法是,正确的输出了我们传递过去的javaBean类型。

项目代码托管到了GitHub,OA

0 0