3. 基礎功能
3.1. 設計BaseDao接口與BaseDaoImpl類
每個實體都應有一個對應的Dao,他封裝了對這個實體的數據庫操作。例
實體Dao接口實現類
========================================================
User--> UserDao--> UserDaoImpl
Role--> RoleDao--> RoleDaoImpl
Department--> DepartmentDao--> DepartmentDaoImpl
Article--> ArticleDao--> ArticleDaoImpl
...
設計Dao接口(抽取接口的公共方法)
BaseDao.java----把每個dao都需要的方法放到這里,好讓他們繼承
public interface BaseDao<T> { void save(T entity); /** * 保存實體 * @param id */ void delete (Long id); /** * 刪除實體 * @param entity */ void update(T entity); /** * 更新實體 * @param id * @return */ T getById(Long id); /** * 按id查詢 * @return */ List<T> getByIds(Long[] id); /** * 按id查詢 * @return */ List<T> findAll(); /** * 查詢所有 */ }
UserDao.java----一些公用的方法繼承BaseDao即可
public interface UserDao extends BaseDao<User>{ //自己有的特殊方法寫在自己這里面 }
RoleDao.java
public interface RoleDao extends BaseDao<Role>{ }
增刪改查等共有方法都有了
設計Dao實現類(抽取實現類的公共方法)
//實現RoleDao,實現所有未實現的方法 public class RoleDaoImpl implements RoleDao{ public void save(Role entity) { } public void delete(Long id) { } public void update(Role entity) { } public Role getById(Long id) { return null; } public List<Role> getByIds(Long[] id) { return null; } public List<Role> findAll() { return null; } }
public class UserDaoImpl implements RoleDao{ public void save(Role entity) { } public void delete(Long id) { } public void update(Role entity) { } public Role getById(Long id) { return null; } public List<Role> getByIds(Long[] id) { return null; } public List<Role> findAll() { return null; } }
public class BaseDaoImpl<T> implements BaseDao<T> { public void save(T entity) { } public void delete(Long id) { } public void update(T entity) { } public T getById(Long id) { return null; } public List<T> getByIds(Long[] id) { return null; } public List<T> findAll() { return null; } }
public class RoleDaoImpl extends BaseDaoImpl<Role> implements RoleDao{ }
public class UserDaoImpl extends BaseDaoImpl<User> implements UserDao{ }
可以看出這兩個實現類的很多方法都重復了,我們把它抽取出來,我們寫一個類它事先實現了里面的公共方法,讓這兩個實現類繼承即可。
BaseDaoImpl里方法是有了,但里面還沒有內容,接下來寫該實現類里面的方法內容
@SuppressWarnings("unchecked") public abstract class BaseDaoImpl<T> implements BaseDao<T> { @Resource private SessionFactory sessionFactory;// 通過注入得到SessionFactory,要把它放到容器里才能注入,在具體的實現類上聲明@Repository private Class<T> clazz; public BaseDaoImpl() { //使用反射技術得到T的真實類型 ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();//獲取當前new類型的泛型的父類類型 this.clazz = (Class<T>) pt.getActualTypeArguments()[0];//獲取第一個類型參數的真實類型,只有一個泛型參數,所以寫0 System.out.println("clazz--->" + clazz); } /** * 獲取當前可用的session對象,用protected修飾方便子類得到session */ protected Session getSession() { return sessionFactory.getCurrentSession(); } public void save(T entity) { // 不需要自己關事務了,spring框架已經幫我們做了,我們用它的事務管理 getSession().save(entity); } public void update(T entity) { getSession().update(entity); } public void delete(Long id) { Object obj = getById(id); if (obj != null) { getSession().delete(obj); } } public T getById(Long id) { return (T) getSession().get(clazz, id); } public List<T> getByIds(Long[] ids) { return getSession().createQuery(// "FROM User WHERE id=IN(:ids)")// .setParameter("", ids) .list(); } public List<T> findAll() { return getSession().createQuery(// "FROM " + clazz.getSimpleName())// .list(); } }
說明:
4, 實體的Dao接口要繼承BaseDao接口。
5, Dao的實現類要繼承DaoImplBase類。
6, 也可以不繼承指定的接口或類,這樣就要自己寫相應的方法。
7, T getById(Long id)與List<T> getByIdList(Long[] idList)不要合並為List getById(Long... ids),因為獲取一個對象時也是返回List,不方便。
獲取 BaseDao的類型參數T的Class
問題:
1, 有了DaoBase與DaoImplBase,還要用UserDao、RoleDao嗎?
答:要用。因為UserDao或RoleDao中的方法可以分為有公有的方法與特有的方法兩部分。公有的方法是通過繼承BaseDao得到的,特有的方法要寫在自己里面(BaseDao中是沒有的)。
2, UserDaoImpl已經繼承了BaseDaoImpl,就不實現UserDao可以嗎?
答:不可以。否則UserDao userDao = new UserDaoImpl(); 就不成立。
使用反射獲取類型參數的真實類型的代碼如下:
public DaoBaseImpl () { Type type = this.getClass().getGenericSuperclass(); ParameterizedType pt = (ParameterizedType) type; this.clazz = (Class<T>) pt.getActualTypeArguments()[0]; } |
說明:
1, 使用Session時,不要自己創建,也不要管理事務,直接調用getSession()即可。
2, 暫時不實現getSession()方法,在后面的事務管理中實現:
protected Session getSession(){
throw new UnsupportedOperationException();
}