每一個實體都應有一個對應的Dao,他封裝了對這個實體的數據庫操做。例java
實體Dao接口實現類spring
========================================================數據庫
User--> UserDao--> UserDaoImplsession
Role--> RoleDao--> RoleDaoImpl框架
Department--> DepartmentDao--> DepartmentDaoImplide
Article--> ArticleDao--> ArticleDaoImplthis
...spa
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便可code
public interface UserDao extends BaseDao<User>{ //本身有的特殊方法寫在本身這裏面 }
RoleDao.java
public interface RoleDao extends BaseDao<Role>{ }
增刪改查等共有方法都有了
//實現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();
}