Loading...
Spring Framework Reference Documentation 7.0.2의 DAO Support의 한국어 번역본입니다.
아래의 경우에 피드백에서 신고해주신다면 반영하겠습니다.
감사합니다 :)
Spring의 Data Access Object (DAO) 지원은 JDBC, Hibernate, JPA와 같은 데이터 액세스 기술을 일관된 방식으로 쉽게 다룰 수 있도록 하는 것을 목표로 합니다. 이를 통해 앞에서 언급한 퍼시스턴스 기술들 간을 상당히 쉽게 전환할 수 있으며, 각 기술에 특화된 예외를 catch해야 한다는 걱정 없이 코드를 작성할 수 있습니다.
Spring은 SQLException과 같은 기술별 예외를 자체 예외 클래스 계층 구조로 편리하게 변환하는 기능을 제공합니다. 이 계층 구조는 DataAccessException을 루트 예외로 합니다.
이러한 예외들은 원래 예외를 wrapping하므로, 무엇이 잘못되었는지에 대한 정보를 잃을 위험이 전혀 없습니다.
JDBC 예외에 더하여, Spring은 JPA 및 Hibernate-specific 예외도 wrapping하여, 이를 집중된 런타임 예외 집합으로 변환할 수 있습니다. 이를 통해, 복구 불가능한 퍼시스턴스 예외 대부분을 적절한 레이어에서만 처리할 수 있으며, 귀찮은 보일러플레이트 catch-and-throw 블록과 DAO에 대한 예외 선언을 피할 수 있습니다. (물론 필요한 곳 어디에서든 예외를 가로채고 처리할 수 있습니다.)
위에서 언급했듯이, JDBC 예외(데이터베이스-specific dialect 포함)도 동일한 계층 구조로 변환되므로, 일관된 프로그래밍 모델 내에서 JDBC를 사용하여 일부 작업을 수행할 수 있습니다.
앞서의 논의는 Spring이 다양한 ORM 프레임워크를 지원하기 위해 제공하는 여러 템플릿 클래스에도 동일하게 적용됩니다. interceptor-based 클래스를 사용하는 경우, 애플리케이션은 HibernateExceptions와 PersistenceExceptions를 직접 처리해야 하며, 바람직하게는 SessionFactoryUtils의 convertHibernateAccessException(..) 또는 convertJpaAccessException(..) 메서드에 각각 위임해야 합니다.
이러한 메서드는 예외를 org.springframework.dao 예외 계층 구조 내의 예외와 호환되는 예외로 변환합니다. PersistenceExceptions는 unchecked이므로, 이들도 그대로 throw될 수 있습니다(다만 예외 측면에서 generic DAO 추상을 희생하게 됩니다).
다음 이미지는 Spring이 제공하는 예외 계층 구조를 보여 줍니다. (이미지에 자세히 나온 클래스 계층 구조는 전체 DataAccessException 계층 구조의 부분집합만을 보여 줍니다.)

Data Access Object(DAO)나 리포지토리가 예외 변환을 제공하도록 보장하는 가장 좋은 방법은 @Repository 어노테이션을 사용하는 것입니다. 이 어노테이션은 또한 컴포넌트 스캐닝 지원이 XML 설정 엔트리를 제공하지 않고도 DAO와 리포지토리를 찾아서 구성할 수 있도록 해 줍니다.
다음 예제는 @Repository 어노테이션 사용 방법을 보여 줍니다:
1@Repository // (1) 2public class SomeMovieFinder implements MovieFinder { 3 // ... 4} 5// Copied!
| 1 | The @Repository annotation. |
1@Repository // (1) 2class SomeMovieFinder : MovieFinder { 3 // ... 4} 5// Copied!
| 1 | The @Repository annotation. |
어떤 DAO나 리포지토리 구현이든, 사용되는 퍼시스턴스 기술에 따라 퍼시스턴스 리소스에 대한 액세스가 필요합니다. 예를 들어, JDBC 기반 리포지토리는 JDBC DataSource에 대한 액세스가 필요하며, JPA 기반 리포지토리는 EntityManager에 대한 액세스가 필요합니다.
이를 가장 쉽게 달성하는 방법은 @Autowired, @Inject, @Resource 또는 @PersistenceContext 어노테이션 중 하나를 사용하여 이 리소스 의존성을 주입받는 것입니다. 다음 예제는 JPA 리포지토리에 대해 동작합니다:
1@Repository 2public class JpaMovieFinder implements MovieFinder { 3 4 @PersistenceContext 5 private EntityManager entityManager; 6 7 // ... 8} 9// Copied!
1@Repository 2class JpaMovieFinder : MovieFinder { 3 4 @PersistenceContext 5 private lateinit var entityManager: EntityManager 6 7 // ... 8} 9// Copied!
classic Hibernate API를 사용하는 경우, 다음 예제에서 보듯이 SessionFactory를 주입할 수 있습니다:
1@Repository 2public class HibernateMovieFinder implements MovieFinder { 3 4 private SessionFactory sessionFactory; 5 6 @Autowired 7 public void setSessionFactory(SessionFactory sessionFactory) { 8 this.sessionFactory = sessionFactory; 9 } 10 11 // ... 12} 13// Copied!
1@Repository 2class HibernateMovieFinder(private val sessionFactory: SessionFactory) : MovieFinder { 3 // ... 4} 5// Copied!
마지막 예제는 typical JDBC 지원에 대한 것입니다. DataSource를 초기화 메서드나 생성자에 주입받아, 이 DataSource를 사용하여 JdbcTemplate 및 SimpleJdbcCall 등 기타 데이터 액세스 지원 클래스를 생성할 수 있습니다.
다음 예제는 DataSource를 autowire하는 방법을 보여 줍니다:
1@Repository 2public class JdbcMovieFinder implements MovieFinder { 3 4 private JdbcTemplate jdbcTemplate; 5 6 @Autowired 7 public void init(DataSource dataSource) { 8 this.jdbcTemplate = new JdbcTemplate(dataSource); 9 } 10 11 // ... 12} 13// Copied!
1@Repository 2class JdbcMovieFinder(dataSource: DataSource) : MovieFinder { 3 4 private val jdbcTemplate = JdbcTemplate(dataSource) 5 6 // ... 7} 8// Copied!
이러한 어노테이션을 활용하도록 애플리케이션 컨텍스트를 구성하는 방법에 대한 자세한 내용은 각 퍼시스턴스 기술에 대한 특정 설명을 참조하십시오.
Further Resources
Data Access with JDBC