All lectures for TW purposes
等級 1 , 課堂 871
開放

DAO簡介

當通過 JDBC 甚至通過 Hibernate 使用數據庫時,代碼往往比我們想要的更麻煩。數據庫查詢通常包含:

  • 數據驗證
  • 設置請求參數
  • 根據查詢參數選擇 HQL 查詢
  • 使用 Criteria API 構建查詢
  • 緩存設置
  • 初始錯誤處理等

因此,通常的做法是創建特殊的類來處理數據庫。這樣的類稱為 DAO,數據訪問對象。他們的任務是隱藏使用數據庫的所有復雜性,並為外部提供一個美觀方便的接口。

例子:

public class EmployeeDAO {

   public List<Employee> getEmployeeList(int from, int count) {
   	String hqlQuery = “from Employee;
   	Query<Employee> query = session.createQuery(hqlQuery, Employee.class);
   	query.setFirstResult(from);
   	query.setMaxResults(count);
   	return query.getResultList();
  }

	public int getEmployeeCount() {
	     String hqlQuery = “select count(*) from Employee;
     	Query<Integer> query = session.createQuery(hqlQuery, Integer.class);
     	return query.getSingleResult();
   }

	public Employee getEmployeeByUniqName(String name) {
	     String hqlQuery = “from Employee where name = :name”;
     	Query<Integer> query = session.createQuery(hqlQuery, Employee.class);
     	query.setParameterr(“name”, name);
     	return query.getSingleResult();
   }
}

我們有一個EmployeeDAO類,借助它我們可以從數據庫中獲取 Employee 類型的對象。該類本身雖然充滿了註釋,但不包含將自身保存到數據庫的方法。

DAO 的好處

這種方法有很多優點:

首先,我們完全隱藏了 DAO 類中的數據庫工作。如果您將來決定將所有查詢從 HQL 重寫為 Criteria API 或 Native Query,這不會以任何方式影響此類外部的代碼。

其次,您可以使這些方法的行為複雜化。您可以添加緩存、事件、參數驗證。這一切都將對外部代碼隱藏。

第三,如果您需要一個尚不存在的方法,只需在此處添加即可。例如,我需要一個方法來返回所有已經過期的用戶任務。然後我就這樣做:

public class EmployeeDAO {

   public List<Task> getExpiredTasks(int userId, int from, int count) {
   	String hqlQuery = “from Task where task.user.id = :id and deadline < curdate();
   	Query<Task> query = session.createQuery(hqlQuery, Task.class);
   	query.setFirstResult(from);
   	query.setMaxResults(count);
   	return query.getResultList();
  }

   public int getExpiredTasksCount(int userId) {
   	String hqlQuery = “select count(*) from Task where task.user.id = :id and deadline < curdate();
   	Query<Integer> query = session.createQuery(hqlQuery, Integer.class);
   	return query.getSingleResult();
  }
}

我在類中添加了兩個方法:

  • getExpiredTasksCount() - 返回用戶的過期任務數
  • getExpiredTasks() - 返回用戶的過期任務列表

我需要方法——我添加了它們。我可以馬上使用它。我稍後會優化它們。

而且,這些方法可以在重寫和優化之前用單元測試覆蓋,所以我們會知道對數據庫的工作仍然和以前一樣。

標準方法

通常,DAO 類具有相同的方法。例如,這些:

T getById(最終長id) 通過 id 獲取對象
List<T> getItems (int from, int count) 獲取給定範圍內的對象列表
列表<T> getAll () 獲取給定類型的所有對象
int獲取計數() 找出對象的數量
T保存(最終 T 實體) 將對象保存到數據庫
T更新(最終T實體) 更新數據庫中的對象
無效刪除(最終 T 實體) 從數據庫中刪除對象
void deleteById (final long entityId) 通過id從數據庫中刪除對象

這些方法在世界上幾乎每個 DAO 類中都有。現在,如果有某種 DAO 類,那麼它有 90% 的可能性會有這樣的方法。

是的,可能還有其他人,但也會有那些人。因為很方便。它允許您不直接與 base 或 Hibernate 交互。

如果有相同的方法,那麼他們需要什麼?沒錯,放在基類中。

它看起來像這樣:

public abstract class AbstractHibernateDao<T > {
    private final Class<T> clazz;
    private SessionFactory sessionFactory;

    public AbstractHibernateDao(final Class<T> clazzToSet)   {
    	this.clazz = clazzToSet;
    }

    public T getById(final long id) {
    	return (T) getCurrentSession().get(clazz, id);
    }

    public List<T> getItems(int from, int count) {
    	Query query = getCurrentSession().createQuery(clazz , "from " + clazz.getName())
    	query.setFirstResult(offset);
    	query.setMaxResults(count);
  	  return query.singleResult();
    }

    public List<T> findAll() {
    	return getCurrentSession().createQuery(clazz, "from " + clazz.getName()).list();
    }

    public T create(final T entity) {
    	getCurrentSession().saveOrUpdate(entity);
    	return entity;
    }

    public T update(final T entity) {
    	return (T) getCurrentSession().merge(entity);
    }

    public void delete(final T entity) {
    	getCurrentSession().delete(entity);
    }

    public void deleteById(final long entityId) {
    	final T entity = getById(entityId);
    	delete(entity);
    }

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

然後我們的EmployeeDAO將如下所示:

public class EmployeeDAO extends AbstractHibernateDAO<Employee> {

   public EmployeeDAO (){
  	super(Employee.class );
   }
}

TaskDAO是這樣的:

public class TaskDAO extends AbstractHibernateDAO<Task> {

   public TaskDAO (){
  	super(Task.class );
   }
}

這兩個類都將擁有我們在AbstractHibernateDAO上聲明的所有方法。統一非常方便實用。

留言
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION