1. 개요
이 기사에서는 Spring 및 Hibernate로 DAO를 구현하는 방법을 보여줍니다 . 핵심 Hibernate 구성에 대해서는 이전 Hibernate 5 with Spring 기사를 확인하십시오.
2. 더 이상 스프링 템플릿이 없습니다.
Spring 3.0 및 Hibernate 3.0.1부터 Spring HibernateTemplate 은 더 이상 Hibernate 세션을 관리하는 데 필요하지 않습니다. 이제 컨텍스트 세션 을 사용할 수 있습니다. 세션은 Hibernate에 의해 직접 관리되고 트랜잭션 범위 전체에서 활성화됩니다.
결과적으로 HibernateTemplate 대신 Hibernate API를 직접 사용하는 것이 이제 모범 사례 입니다. 이렇게 하면 DAO 계층 구현이 Spring에서 완전히 분리됩니다.
2.1. HibernateTemplate 없는 예외 번역
예외 변환은 HibernateTemplate 의 책임 중 하나였습니다 . 낮은 수준의 Hibernate 예외를 더 높은 수준의 일반적인 Spring 예외로 변환하는 것입니다.
템플릿이 없으면 이 메커니즘은 @Repository 어노테이션 이 달린 모든 DAO에 대해 여전히 활성화되고 활성화 됩니다. 후드 아래에서 이것은 Spring 컨텍스트에서 발견된 모든 PersistenceExceptionTranslator 를 사용하여 모든 @Repository 빈에 조언하는 Spring 빈 포스트 프로세서를 사용합니다 .
기억해야 할 한 가지는 예외 번역이 프록시를 사용한다는 것입니다. Spring이 DAO 클래스 주위에 프록시를 생성할 수 있으려면 이들은 final 로 선언되지 않아야 합니다 .
2.2. 템플릿 없이 Hibernate 세션 관리
컨텍스트 세션에 대한 Hibernate 지원이 나왔을 때 HibernateTemplate은 본질적 으로 구식이 되었습니다. 사실, 클래스의 Javadoc은 이제 이 측면을 강조합니다(원본에서 굵게 표시됨).
참고: Hibernate 3.0.1부터는 트랜잭션 Hibernate 액세스 코드도 일반 Hibernate 스타일로 코딩할 수 있습니다. 따라서 새로 시작된 프로젝트의 경우 {@link org.hibernate.SessionFactory#getCurrentSession()}을 기반으로 데이터 액세스 객체를 코딩하는 표준 Hibernate3 스타일을 대신 채택하는 것을 고려하십시오.
3. 다오
기본 DAO 부터 시작하겠습니다 . 이는 일반적인 일반 작업을 지원하고 각 엔터티에 대해 확장할 수 있는 추상적이고 매개 변수화된 DAO입니다.
public abstract class AbstractHibernateDao<T extends Serializable> {
private Class<T> clazz;
@Autowired
protected SessionFactory sessionFactory;
public final void setClazz(final Class<T> clazzToSet) {
clazz = Preconditions.checkNotNull(clazzToSet);
}
// API
public T findOne(final long id) {
return (T) getCurrentSession().get(clazz, id);
}
public List<T> findAll() {
return getCurrentSession().createQuery("from " + clazz.getName()).list();
}
public T create(final T entity) {
Preconditions.checkNotNull(entity);
getCurrentSession().saveOrUpdate(entity);
return entity;
}
public T update(final T entity) {
Preconditions.checkNotNull(entity);
return (T) getCurrentSession().merge(entity);
}
public void delete(final T entity) {
Preconditions.checkNotNull(entity);
getCurrentSession().delete(entity);
}
public void deleteById(final long entityId) {
final T entity = findOne(entityId);
Preconditions.checkState(entity != null);
delete(entity);
}
protected Session getCurrentSession() {
return sessionFactory.getCurrentSession();
}
}
여기에서 흥미로운 몇 가지 측면이 있습니다. 논의한 것처럼 추상 DAO는 Spring 템플릿(예: HibernateTemplate ) 을 확장하지 않습니다 . 대신, Hibernate SessionFactory 는 DAO에 직접 주입되고 그것이 노출 하는 컨텍스트 세션 을 통해 메인 Hibernate API의 역할을 갖게 될 것입니다 :
this.sessionFactory.getCurrentSession();
또한 생성자는 일반 작업에서 사용할 매개 변수로 엔터티 의 클래스 를 받습니다.
이제 Foo 엔터티 에 대한 이 DAO의 구현 예를 살펴보겠습니다 .
@Repository
public class FooDAO extends AbstractHibernateDAO< Foo > implements IFooDAO{
public FooDAO(){
setClazz(Foo.class );
}
}
4. 결론
이 기사에서는 Hibernate 및 Spring을 사용한 지속성 계층의 구성 및 구현에 대해 설명했습니다.
트랜잭션 및 Hibernate 세션을 관리하기 위해 Spring을 구성할 때 발생할 수 있는 함정뿐만 아니라 DAO 계층에 대한 템플릿 의존을 중지하는 이유에 대해 논의했습니다. 최종 결과는 컴파일 시간에 Spring에 거의 의존하지 않는 가볍고 깨끗한 DAO 구현입니다.
이 간단한 프로젝트의 구현은 github 프로젝트 에서 찾을 수 있습니다 .