SSH combat OA 03: Design BaseDAo

The previous section has set up the framework environment of the project. And did a simple test. In this section, we mainly design the Dao shared class. Before doing this work, let's look at a problem: in the process of development, we found that the main function of the DAO layer is to add, delete, modify, and check the database. For example, there are four modules: user management, department management, role management, and article management:

entity Dao interface Implementation class
User UserDao UserDaoImpl
Role RoleDao RoleDaoImpl
Department DepartmentDao DepartmentDaoImpl
Article ArticleDao ArticleDaoImpl

They each have the following methods:

entity Dao method
User UserDao save(User user), update(), delete(), find()
Role RoleDao save(Role role), update(), delete(), find()
Student StudentDao save(Student student), update(), delete(), find()

The main function of these four Dao classes is to add, delete, modify, and query the corresponding tables in the data. At this time, in order to avoid repeated operations, their basic operation methods can be extracted as a common method of the basic class.

kind method
BaseDao save(T t), update(), delete(), find()

The model of the class is shown in the figure:
write picture description here
Based on Java's single inheritance and multiple reality principle, we can design a general BaseDao interface, which includes save(), delete(), update(), getById(), getByIds(), findAll() For common methods, this Dao has a basic implementation class BaseDaoImpl, which implements all methods of this common interface. The dao implementation class corresponding to User can inherit BaseDaoImpl and also implement the UserDao interface. The Dao implementation class corresponding to Role can also inherit BaseDaoImpl and implement the RoleDao interface. The common method is placed in the BaseDao interface, and the unique method of the entity corresponding to the individual is placed in its own interface, thus reducing the repetitive workload!

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();
    }
}

Since the common class cannot determine the specific entity, only generics can be used. The type of the entity passed in during the calling process needs to be realized by the java reflection mechanism. The key code is these two lines of code in our constructor:

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

This class uses the hibernate session many times, so the session acquisition is directly made into a protected-level method. In order to better use this method for subclass inheritance, it should not be written as a private private level.

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

It should be noted here that the basic implementation class cannot be new, only its subclasses can be new, so the abstract abstract type must be written here.

In this way, this public class can be called from Dao of different modules.
User add, delete, modify and check the corresponding UserDao interface

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 implementation class

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;

@Repository
public 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;
    }
}

Department management add, delete, modify and check the corresponding interface 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 implementation class

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);

}

Let's do the junit test:
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());
        }
    }
}

We found that the constructor called to BaseDaoImpl is the correct output of the javaBean type we passed in the past.

The project code is hosted on GitHub, OA

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325976000&siteId=291194637