Spring DAO 대 Spring ORM 대 Spring JDBC


103

Spring에서 지원하는 데이터 액세스 기술을 살펴 보았는데 여러 옵션이 언급되어 있고 그 차이에 대해 잘 모르겠습니다.

내가 이해하는 바와 같이 Spring JDBC는 평범한 예전 방식을 통해 데이터베이스에 액세스하기위한 상용구 코드를 줄이기위한 템플릿을 제공합니다. 사용자는 SQL 쿼리를 직접 작성합니다.

Spring-ORM은 Hibernate, My (i) Batis 등과 같은 ORM 기술을 통해 데이터베이스에 액세스하기위한 단순화 된 템플릿을 제공합니다.

Spring 웹 사이트에 따른 Spring-DAO :

Spring의 DAO (Data Access Object) 지원은 JDBC, Hibernate 또는 JDO와 같은 데이터 액세스 기술을 일관된 방식으로 쉽게 사용할 수 있도록하는 데 목적이 있습니다.

DB에 액세스하는 다른 방법을 겨냥한 ORM 대 JDBC에 대해 조금 분명합니다. 그러나 Spring-DAO는 혼란 스럽습니다!

누구든지이 세 가지의 차이점을 정확히 설명해 주시겠습니까? 어떤 시나리오에서 어떤 것이 선호되어야합니까?

또한 Spring-DATA사용 가능한 다른 프로젝트가 있습니다 ( http://projects.spring.io/spring-data/ ) 이제 Spring에서 지원하는 모든 데이터 액세스 기술에 대한 일종의 부모 프로젝트입니까 아니면 Spring의 새로운 이름입니까? -DAO?

답변:


162

다음은 언급 된 각 기술에 대한 소개입니다.

봄 -DAO

Spring-DAO는 엄격한 의미에서 스프링 모듈이 아니라 DAO를 작성하고 잘 작성하도록 지시해야하는 규칙입니다. 따라서 데이터에 액세스하기위한 인터페이스, 구현 또는 템플릿을 제공하지 않습니다. DAO를 작성할 때 @Repository기본 기술 (JDBC, Hibernate, JPA 등)에 연결된 예외가 적절한 DataAccessException하위 클래스 로 일관되게 변환되도록 DAO에 주석을 달아야합니다 .

예를 들어, 이제 Hibernate를 사용하고 있고 서비스 계층 HibernateException이 이에 대응하기 위해 포착한다고 가정 합니다. JPA로 변경하면 DAO 인터페이스가 변경되어서는 안되며 서비스 계층은 여전히를 catch하는 블록으로 컴파일 HibernateException되지만 DAO가 이제 JPA를 던지고 있으므로 이러한 블록에 들어 가지 않습니다 PersistenceException. @RepositoryDAO에서 사용 하면 기본 기술에 연결된 예외가 Spring으로 변환됩니다 DataAccessException. 서비스 계층은 이러한 예외를 포착하고 지속성 기술을 변경하기로 결정한 경우 Spring DataAccessExceptions이 네이티브 예외를 번역했기 때문에 동일한 Spring 이 여전히 throw됩니다.

그러나 다음과 같은 이유로 사용이 제한됩니다.

  1. 공급자가 트랜잭션을 롤백했을 수 있으므로 (정확한 예외 하위 유형에 따라) 일반적으로 지속성 예외를 포착해서는 안되며, 따라서 대체 경로로 실행을 계속해서는 안됩니다.
  2. 예외의 계층 구조는 일반적으로 Spring이 제공하는 것보다 공급자에서 더 풍부하며 한 공급자에서 다른 공급자로의 명확한 매핑이 없습니다. 이것에 의존하는 것은 위험합니다. 그러나 @Repository스캔 절차에 의해 빈이 자동으로 추가 되므로 DAO에를 주석으로 추가하는 것이 좋습니다 . 또한 Spring은 주석에 다른 유용한 기능을 추가 할 수 있습니다.

Spring-JDBC

Spring-JDBC는 배관 코드를 제거하고 SQL 쿼리 및 매개 변수에 집중하는 데 도움이되는 JdbcTemplate 클래스를 제공합니다. 으로 구성하기 만하면 DataSource다음과 같은 코드를 작성할 수 있습니다.

int nbRows = jdbcTemplate.queryForObject("select count(1) from person", Integer.class);

Person p = jdbcTemplate.queryForObject("select first, last from person where id=?", 
             rs -> new Person(rs.getString(1), rs.getString(2)), 
             134561351656L);

Spring-JDBC는 DAO를 개발하기 위해 확장 할 수있는 JdbcDaoSupport도 제공합니다. 기본적으로 두 가지 속성, 즉 DAO 메서드를 구현하는 데 사용할 수있는 DataSource 및 JdbcTemplate을 정의합니다. 또한 SQL 예외에서 Spring DataAccessExceptions로 예외 변환기를 제공합니다.

일반 jdbc를 사용하려는 경우이 모듈을 사용해야합니다.

봄 ORM

Spring-ORM은 JPA, JDO, Hibernate 및 iBatis와 같은 많은 지속성 기술을 다루는 우산 모듈입니다. 이러한 각 기술에 대해 Spring은 각 기술이 Spring의 구성 원칙에 따라 사용될 수 있도록 통합 클래스를 제공하고 Spring 트랜잭션 관리와 원활하게 통합됩니다.

각 기술에 대해 구성은 기본적으로 DataSource일종의 SessionFactory또는 EntityManagerFactory기타 빈에 빈을 주입하는 것으로 구성됩니다 . 순수한 JDBC의 경우 JDBC는 DataSource에만 의존하므로 JdbcTemplate과는 별도로 이러한 통합 클래스가 필요하지 않습니다.

JPA 또는 Hibernate와 같은 ORM을 사용하려는 경우 spring-jdbc가 필요하지 않고이 모듈 만 필요합니다.

스프링 데이터

Spring-Data는 SQL 및 NOSQL 데이터 소스를 모두 포함하는보다 일반적인 방법으로 데이터 (DAO + 주석)에 액세스하는 방법을 정의하는 공통 API를 제공하는 우산 프로젝트입니다.

초기 아이디어는 개발자가 기술에 구애받지 않는 방식으로 DAO (파인더 메서드) 및 엔티티 클래스에 대한 인터페이스를 작성하고 구성만을 기반으로 (DAO 및 엔티티에 대한 주석 + 스프링 구성, xml 또는 java 기반), 구현 기술, 즉 JPA (SQL) 또는 redis, hadoop 등 (NOSQL)을 결정합니다.

finder 메소드 이름에 대해 spring에서 정의한 이름 지정 규칙을 따르는 경우 가장 간단한 경우에 finder 메소드에 해당하는 쿼리 문자열을 제공 할 필요조차 없습니다. 다른 상황에서는 finder 메소드의 주석 내에 쿼리 문자열을 제공해야합니다.

애플리케이션 컨텍스트가로드되면 Spring은 데이터 액세스 기술과 관련된 모든 상용구 코드를 포함하는 DAO 인터페이스에 대한 프록시를 제공하고 구성된 쿼리를 호출합니다.

Spring-Data는 비 SQL 기술에 집중하지만 여전히 JPA (유일한 SQL 기술) 용 모듈을 제공합니다.

무엇 향후 계획

이 모든 것을 알았으므로 이제 무엇을 선택할지 결정해야합니다. 여기서 좋은 소식은 기술에 대한 최종 선택을 할 필요가 없다는 것입니다. 이것은 실제로 Spring의 힘이있는 곳입니다. 개발자로서 여러분은 코드를 작성할 때 비즈니스에 집중하고, 잘한다면 기본 기술을 변경하는 것은 구현 또는 구성 세부 사항입니다.

  1. 엔티티에 대한 POJO 클래스를 사용하여 데이터 모델을 정의하고 엔티티 속성 및 다른 엔티티와의 관계를 나타내는 get / set 메소드를 정의하십시오. 확실히 기술을 기반으로 엔티티 클래스와 필드에 주석을 달아야하지만 지금은 POJO로 시작하기에 충분합니다. 지금은 비즈니스 요구 사항에 집중하십시오.
  2. DAO에 대한 인터페이스를 정의하십시오. 1 DAO는 정확히 1 개의 엔터티를 다루지 만 관계를 탐색하여 추가 엔터티를로드 할 수 있어야하므로 각 엔터티에 대해 DAO가 반드시 필요하지는 않습니다. 엄격한 이름 지정 규칙에 따라 파인더 메소드를 정의하십시오.
  3. 이를 기반으로 다른 사람이 DAO에 대한 모의를 사용하여 서비스 계층 작업을 시작할 수 있습니다.
  4. 다양한 지속성 기술 (sql, no-sql)을 학습하여 필요에 가장 적합한 것을 찾고 그중 하나를 선택합니다. 이를 기반으로 엔티티에 주석을 달고 DAO를 구현합니다 (또는 spring-data를 사용하기로 선택한 경우 Spring이이를 구현하도록합니다).
  5. 비즈니스 요구 사항이 진화하고 데이터 액세스 기술이이를 지원하기에 충분하지 않은 경우 (예 : JDBC 및 몇 개의 엔티티로 시작했지만 이제 더 풍부한 데이터 모델이 필요하며 JPA가 더 나은 선택입니다) 구현을 변경해야합니다. DAO의 경우 엔티티에 몇 가지 주석을 추가하고 스프링 구성을 변경하십시오 (EntityManagerFactory 정의 추가). 나머지 비즈니스 코드는 변경으로 인한 다른 영향을 보지 않아야합니다.

참고 : 트랜잭션 관리

Spring은 트랜잭션 관리를위한 API를 제공합니다. 데이터 액세스를 위해 spring을 사용할 계획이라면 Spring이 잘 통합되므로 트랜잭션 관리에도 사용해야합니다. Spring에서 지원하는 각 데이터 액세스 기술에 대해 로컬 트랜잭션을위한 매칭 트랜잭션 관리자가 있거나 분산 트랜잭션이 필요한 경우 JTA를 선택할 수 있습니다. 모두 동일한 API를 구현하므로 (다시 한 번) 기술 선택은 비즈니스 코드에 더 이상 영향을주지 않고 변경 될 수있는 구성에 불과합니다.

참고 : Spring 문서

언급 한 Spring 문서에 대한 링크는 다소 오래되었습니다. 다음은 최신 릴리스 (4.1.6, 모든 항목 포함)의 설명서입니다.

Spring-data는 Spring 프레임 워크의 일부가 아닙니다. 원칙에 익숙해지기 위해 먼저 읽어야하는 공통 모듈이 있습니다. 문서는 여기에서 찾을 수 있습니다.


나는 여기 (Spring Data와 같은) 일부 설명에서 "우산"이라는 용어를 사용 하여이 답변에 감사하며 (우산이 더 도메인에 특화된 것이 아니라) 하위 구성 요소 / 모듈이 있음을 식별합니다. 그리고 SpringData를 언급하는 것은 질문에서 언급되지 않았지만 여기서 문맥에서 매우 유용합니다.
cellepo

하지 않습니다 spring-jdbc여기에 언급되지 않은 다른 유용한 도구를 제공? 예를 들어 SimpleJdbcInsert단일 항목 삽입과 대량 (물론 합리적인 규모까지) 모두에 매우 깨끗하고 유용합니다.
Nom1fan

3

Spring DAO ( D ata A ccess O bject) : JDBC 구현 프레임 워크에 추상 인터페이스를 제공하는 객체입니다. 즉, Spring DAO는 개별 지원 클래스를 사용하여 JDBC 및 Hibernate, MyBatis, JPA, JDO에 액세스하기위한 일반화 된 개념입니다. 그리고 Annotation 을 정의하여 일반화 된 예외 계층 구조를 제공합니다 @Repository. 이 주석은 Spring의 데이터 액세스 전략에 구애받지 않는 계층으로 SQL 예외 변환 을 위한 Spring 컨테이너를 정의합니다 . SQLExceptionDataAccessException

즉, 플랫폼 특정 예외가 포착 된 다음 Spring의 확인되지 않은 데이터 액세스 예외 중 하나로 다시 발생합니다.


Spring JDBC : 일반 JDBC의 경우 , (wraps )와 DataSource같은 템플릿 클래스 에만 의존 하고 교차 절단 문제를 줄이기 위해이 모듈을 사용합니다 . JdbcTemplateNamedParameterJdbcTemplateJdbcTemplateSimpleJdbcTemplate

public class EmployeeDao {  
private JdbcTemplate jdbcTemplate;  

public void setJdbcTemplate(JdbcTemplate jdbcTemplate) {  
    this.jdbcTemplate = jdbcTemplate;  
}  

public int saveEmployee(Employee e){  
    return jdbcTemplate.update(query);  
}  
public int updateEmployee(Employee e){  
    return jdbcTemplate.update(query);  
}  
public int deleteEmployee(Employee e){  
       return jdbcTemplate.update(query);  
}  

}  

그리고 Spring XML에서 :

<bean id="jdbcTemplate" class="org.springframework.jdbc.core.JdbcTemplate">
    <property name="dataSource" ref="dataSource"/>
</bean>

봄 JDBC는 또한 제공 JdbcDaoSupport, NamedParameterJdbcDaoSupport, SimpleJdbcDaoSupport,있는 지원 (즉, 편리한 확장하고 우리 자신의 개발) 방식으로 DAO 다음과 같이 추상적 인 인터페이스를 :

public interface EmployeeDao {

    public void saveEmployee(Employee emp);
}

public class EmployeeDaoImpl extends JdbcDaoSupport implements EmployeeDao{

    @Override
    public void saveEmployee(Employee emp) {

        Object[] inputs = new Object[] {emp.getName(), emp.getSalary(), emp.getDept()};
        getJdbcTemplate().update(query, inputs);
    }
}

그리고 봄 XML에서 :

<bean id="employeeDAO" class="EmployeeDaoImpl">
        <property name="dataSource" ref="dataSource" />
    </bean>

Spring ORM : Hibernate, JPA, MyBatis와 같은 ORM 도구 지원의 경우 DataSource다음 클래스 및 각 DaoSupport클래스 와 함께 주입하여 Spring을 쉽게 통합 합니다.

  • SessionFactory 최대 절전 모드
  • EntityManagerFactory JPA의 경우
  • SqlSessionFactory MyBatis 용

1

spring-dao lib는 버전 2.0.8 (2008 년 1 월)에서 중지되었습니다. spring-dao의 클래스는 spring-tx로 복사되었습니다. 따라서 spring-dao에서 찾은 클래스가 필요하면 대신 spring-tx에 종속성을 추가하십시오 . ( 출처 .)


0

SomeObjectDao다음 과 같은 인터페이스 를 생성 한 다음 JdbcSomeObjectDao, HibernateSomeObjectDao. 그런 다음 SomeObjectService클래스에서 SomeObjectDao인터페이스에서 작업하고 구체적인 구현 중 하나를 삽입합니다. 따라서의 각 구현은 SomeObjectDaoJDBC 또는 ORM 등을 사용하는지 여부에 관계없이 세부 정보를 숨 깁니다.

일반적으로 JDBC 및 ORM의 다른 구현은 다른 종류의 예외를 발생시킵니다. Spring의 DAO 지원 은 이러한 다른 기술 별 예외를 일반적인 Spring DAO 예외에 매핑 할 수 있습니다. 따라서 실제 구현에서 더 많이 분리됩니다. 또한 Spring의 DAO 지원*DataSupportDAO 개발에 더욱 도움이되는 추상 클래스 세트를 제공합니다 . 따라서 SomeObjectDao인터페이스를 구현하는 것 외에도 Spring의 *DataSupport클래스 중 하나를 확장 할 수 있습니다 .


그래서 spring-dao는 Hibernate / JDO / JDBC에 특정한 예외를 추상화하고 표준 예외 세트를 제공한다는 것을 의미합니까? 그것은 어떤 있습니까 templates액세스 DB에를? 아니면 다른 스프링 구성 요소와 함께 사용되는 추상화입니까? 예를 들어 spring-dao 만 사용하여 db에 액세스하는 코드를 작성할 수 있습니까 (spring-jdbc, spring-orm, hibernate 또는 다른 프레임 워크를 사용하지 않고)?
Pat

0

추가 정보로. SpringData JPA를 사용하는 것이 좋습니다. @Repository, @Service와 같은 주석 사용. 예를 들어 보겠습니다.

@Repository("customerEntitlementsRepository")
public interface CustomerEntitlementsRepository extends CrudRepository<BbsExerul, BbsExerulPK> {

  @Query(value = "SELECT " + "CONTRACT_NUMBER, EXECUTIVE_NUMBER, " + "GROUP_VALUE, " + "CODE, "
      + "SUBCODE, " + "CURRENCY " + "FROM BBS_EXERUL " + "WHERE CONTRACT_NUMBER =:clientId AND "
      + "EXECUTIVE_NUMBER =:representativeId", nativeQuery = true)
  Collection<CustomerEntitlementsProjection> getFieldsExerul(@Param("clientId") String clientId,
      @Param("representativeId") String representativeId);

}

CustomerEntitlementsProjection이 Spring 프로젝션 인 경우 엔티티 또는 DTO pojo와 연결됩니다.

@Projection(name = "customerEntitlementsProjection", types = { BbsExerul.class })
public interface CustomerEntitlementsProjection {

  String getContractNumber();

  String getExecutiveNumber();

1
코드를 읽을 수 있도록 코드 블록으로 형식을 지정하십시오.
SomePerformance
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.