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 またはネイティブ クエリに書き直すことにした場合でも、このクラスの外部のコードにはまったく影響しません。
次に、これらのメソッドの動作が複雑になる可能性があります。キャッシュ、イベント、パラメータ検証を追加できます。これはすべて外部コードから隠蔽されます。
第三に、まだ存在しないメソッドが必要な場合は、ここに追加するだけです。たとえば、すでに期限切れになっているすべてのユーザー タスクを返すメソッドが必要です。それから私はこれをやります:
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();
}
}
クラスに 2 つのメソッドを追加しました。
- getExpiredTasksCount() - ユーザーの期限切れタスクの数を返します。
- getExpiredTasks() - ユーザーの期限切れタスクのリストを返します。
メソッドが必要なので追加しました。そしてすぐに使えます。後で最適化します。
さらに、これらのメソッドは書き換えや最適化の前に単体テストでカバーできるため、データベースの操作が以前と同じであることがわかります。
標準的なアプローチ
多くの場合、DAO クラスには同じメソッドがあります。たとえば、次のようなものがあります。
T getById (最終的な長い ID) | ID でオブジェクトを取得する |
List<T> getItems (int from, int count) | 指定された範囲内のオブジェクトのリストを取得します |
List<T> getAll () | 指定されたタイプのすべてのオブジェクトを取得します |
int getCount () | オブジェクトの数を調べます |
T保存(最終的な T エンティティ) | オブジェクトをデータベースに保存する |
T更新(最終 T エンティティ) | データベース内のオブジェクトを更新する |
void delete (最後の T エンティティ) | データベースからオブジェクトを削除する |
void deleteById (最後の長いentityId) | ID によってデータベースからオブジェクトを削除します |
これらのメソッドは、世界中のほぼすべての DAO クラスにあります。さて、ある種の DAO クラスがある場合、90% の確率でそのようなメソッドが含まれます。
はい、他にもあるかもしれませんが、それらもあるでしょう。とても便利だからです。また、ベースや 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で宣言したすべてのメソッドを持ちます。統合は非常に便利で実用的です。
GO TO FULL VERSION