DAO 소개

JDBC 또는 심지어 Hibernate를 통해 데이터베이스로 작업할 때 코드는 종종 우리가 원하는 것보다 더 성가신 것으로 판명됩니다. 데이터베이스 쿼리에는 종종 다음이 포함됩니다.

  • 데이터 유효성 검사
  • 요청 매개변수 설정
  • 쿼리 매개변수에 따른 HQL 쿼리 선택
  • Criteria API를 사용하여 쿼리 구성
  • 캐싱 설정
  • 초기 오류 처리 등

따라서 일반적인 관행은 데이터베이스 작업을 위한 특수 클래스를 만드는 것입니다. 이러한 클래스를 DAO(Data Access Object)라고 합니다. 그들의 임무는 데이터베이스 작업의 모든 복잡성을 숨기고 외부에 아름답고 편리한 인터페이스를 제공하는 것입니다.

예:

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();
   }
}

데이터베이스에서 Employee 유형의 개체를 가져오는 데 도움이 되는 EmployeeDAO 클래스가 있습니다 . 클래스 자체는 주석으로 채워져 있지만 데이터베이스에 저장하는 방법을 포함하지 않습니다.

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();
  }
}

클래스에 두 가지 방법을 추가했습니다.

  • getExpiredTasksCount() - 사용자의 만료된 작업 수를 반환합니다.
  • getExpiredTasks() - 사용자의 만료된 작업 목록을 반환합니다.

방법이 필요합니다. 방법을 추가했습니다. 그리고 바로 사용할 수 있습니다. 나중에 최적화하겠습니다.

또한 이러한 방법은 재작성 및 최적화 전에 단위 테스트로 처리할 수 있으므로 데이터베이스 작업이 이전과 동일하게 유지되었음을 알 수 있습니다.

표준 접근법

매우 자주 DAO 클래스에는 동일한 메서드가 있습니다. 예를 들어 다음과 같습니다.

T getById (최종 긴 ID) ID로 객체 가져오기
List<T> getItems (int from, int count) 주어진 범위 내의 객체 목록 가져오기
리스트<T> getAll () 주어진 유형의 모든 객체 가져오기
정수 getCount () 물건의 수를 알아내다
T 저장 (최종 T 엔터티) 객체를 데이터베이스에 저장
T 업데이트 (최종 T 엔티티) 데이터베이스의 개체 업데이트
무효 삭제 (최종 T 엔터티) 데이터베이스에서 개체 삭제
무효 deleteById (최종 긴 entityId) ID로 데이터베이스에서 개체 삭제

이러한 메서드는 전 세계 거의 모든 DAO 클래스에서 찾을 수 있습니다. 이제 어떤 종류의 DAO 클래스가 있으면 90% 확률로 그러한 메서드가 있을 것입니다.

예, 다른 사람이 있을 수 있지만 그런 사람도 있을 것입니다. 매우 편리하기 때문입니다. 그리고 기본 또는 최대 절전 모드와 직접 상호 작용하지 않도록 합니다.

동일한 방법이 있다면 무엇이 필요합니까? 맞습니다. 기본 클래스에 넣으십시오.

다음과 같이 보입니다.

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 에서 선언한 모든 메서드를 갖게 됩니다 . 통일은 매우 편리하고 실용적입니다.