通常來說一個項目中,我們會使用到多個Dao,例如一個學生管理系統,可能就包含AdminDao,StudentDao,CourseDao等模塊,每個Dao都有相同的增刪改查代碼,每個Dao去寫也是可以的,不過代碼量就會偏多。實際上可以通過泛型,來抽取出一個BaseDao,這個BaseDao包含了各個Dao常用的增刪改查代碼,創建新的Dao時,繼承BaseDao,就可以少寫很多重複代碼。
下面我們先寫一個普通的Dao,然後抽取出BaseDao,看Dao前後代碼變化。
1、抽取前dao接口代碼
package cn.tax.nsfw.user.dao;
import java.io.Serializable;
import java.util.List;
import cn.tax.nsfw.user.entity.User;
public interface UserDao {
public void save(User user);// 保存
public void delete(User user);// 刪除用戶
public void update(User user);// 更新用戶
public User findById(Serializable id);// 根據主鍵查找用戶
public List<User> getAll();// 查看所有
}
2、抽取前dao實現類
package cn.tax.nsfw.user.dao.impl;
import java.io.Serializable;
import java.util.List;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import cn.tax.nsfw.user.dao.UserDao;
import cn.tax.nsfw.user.entity.User;
public class UserDaoImpl extends HibernateDaoSupport implements UserDao {
public void save(User user) {
getSession().save(user);
}
public void delete(User user) {
getSession().delete(user);
}
public void update(User user) {
getSession().update(user);
}
public User findById(Serializable id) {
return (User) getSession().get(User.class, id);
}
public List<User> getAll() {
return getSession().createQuery("FROM User").list();
}
}
3、創建BaseDao接口
這個接口不需要改動太多,只需要把基本的增刪改查代碼改成泛型(把dao接口的複製過來,把User 改成 T ,)T是可以任意一個字母,只是習慣都用T (泛型知識)。
package cn.tax.nsfw.core.dao;
import java.io.Serializable;
import java.util.List;
public interface BaseDao<T> {
public void save(T entity);// 保存
public void delete(T entity);// 刪除用戶
public void update(T entity);// 更新用戶
public T findById(Serializable id);// 根據主鍵查找用戶
public List<T> getAll();// 查看所有
}
4、創建BaseDao實現
實現了BaseDao接口後,最主要的做的事情是要獲取到T的類型。
因爲在查詢數據庫的時候Hibernate需要用到這個字段去拼接查詢語句
其實在service層調用的時候,就已經知道T的傳入類型,問題就在於怎麼在BaseDao實現類中獲取到這個傳入類型,看下面這行代碼,這行代碼返回的是包含泛型的父類:
a、ParameterizedType pt =
(ParameterizedType)this.getClass().getGenericSuperclass();
具體打印出來是:cn.tax.nsfw.core.dao.impl.BaseDaoImpl< cn.tax.nsfw.user.entity.User >
b、clazz = (Class< T >)pt.getActualTypeArguments()[0]
這行代碼返回的是此類型實際類型參數的Type對象的數組,數組裏放的都是對應類型的Class
具體打印出來的是:cn.tax.nsfw.user.entity.User
c、到這裏就已經拿到了在service層傳進來的實體類類型。
最後用的時候再通過clazz.getSimpleName()就可以拿到“User”字段去拼接查詢語句了
BaseDao實現類代碼:
package cn.tax.nsfw.core.dao.impl;
import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.util.List;
import org.springframework.orm.hibernate3.support.HibernateDaoSupport;
import cn.tax.nsfw.core.dao.BaseDao;
public class BaseDaoImpl<T> extends HibernateDaoSupport implements BaseDao<T> {
Class<T> clazz;
ParameterizedType pt;
public BaseDaoImpl() {
pt = (ParameterizedType)this.getClass().getGenericSuperclass(); //cn.tax.nsfw.core.dao.impl.BaseDaoImpl<cn.tax.nsfw.user.entity.User>
clazz = (Class<T>)pt.getActualTypeArguments()[0]; //cn.tax.nsfw.user.entity.User
}
public void save(T entity) {
getSession().save(entity);
}
public void delete(T entity) {
getSession().delete(entity);
}
public void update(T entity) {
getSession().update(entity);
}
public T findById(Serializable id) {
return (T) getSession().get(clazz, id);
}
public List<T> getAll() {
return getSession().createQuery("FROM " + clazz.getSimpleName()).list();
}
}
5、修改抽取前的Dao接口
A、繼承BaseDao< User >
B、把BaseDao< User >中有的方法都可以註釋掉(刪掉),
C、以後有新增的業務,只需要加新增的業務代碼。整個dao就沒有多少代碼了。
package cn.tax.nsfw.user.dao;
import cn.tax.nsfw.core.dao.BaseDao;
import cn.tax.nsfw.user.entity.User;
public interface UserDao extends BaseDao<User> {
//public void save(User user);// 保存
//public void delete(User user);// 刪除用戶
//public void update(User user);// 更新用戶
//public User findById(Serializable id);// 根據主鍵查找用戶
//public List<User> getAll();// 查看所有
}
6、修改抽取前的dao實現類
A、繼承BaseDaoImpl< Use r> ,因爲BaseDaoImpl< User >繼承了hibernateDaoSupport,所以UserDaoImpl 也是可以用hibernateDaoSupport的方法的
B、同樣是把BaseDaoImpl< User >中已有的方法註釋掉(刪掉),只需添加新的業務代碼。
package cn.tax.nsfw.user.dao.impl;
import cn.tax.nsfw.core.dao.impl.BaseDaoImpl;
import cn.tax.nsfw.user.dao.UserDao;
import cn.tax.nsfw.user.entity.User;
public class UserDaoImpl extends BaseDaoImpl<User> implements UserDao {
//如果沒有新的業務,dao層代碼基本是空的,所有基本的增刪改查都交給baseDao來處理,
//這裏只需要實現一些新增業務代碼就可以了
/*public void save(User user) {
getSession().save(user);
}
public void delete(User user) {
getSession().delete(user);
}
public void update(User user) {
getSession().update(user);
}
public User findById(Serializable id) {
return (User) getSession().get(User.class, id);
}
public List<User> getAll() {
return getSession().createQuery("FROM User").list();
}*/
}