web-dev-qa-db-ja.com

Spring DAO vs Spring ORM vs Spring JDBC

Springでサポートされているデータアクセステクノロジーを試していましたが、複数のオプションが言及されていることに気づき、それらの違いについてはわかりません。

私が理解しているように、Spring JDBCは、昔ながらの方法でデータベースにアクセスするための定型コードを減らすためのテンプレートを提供します-あなたはあなた自身のSQLクエリを書きます。

Spring-ORMは、Hibernate、My(i)BatisなどのORMテクノロジーを介してデータベースにアクセスするための簡易テンプレートを提供します。

SpringのWebサイトによるSpring-DAO:

Springのデータアクセスオブジェクト(DAO)サポートは、JDBC、Hibernate、JDOなどのデータアクセステクノロジーを一貫した方法で簡単に操作できるようにすることを目的としています。

ORMとJDBCはDBにアクセスするさまざまな方法を対象としているため、私は少し明確です。しかし、Spring-DAOは紛らわしいだけです!

誰もがこれら3つの違いは何であるかを明確に教えていただけますか?どのシナリオでどちらを優先すべきですか?

また、別のプロジェクトSpring-DATAも利用できます( http://projects.spring.io/spring-data/ )今、それはすべてのデータアクセス技術の親プロジェクトのようなものですSpringによってサポートされていますか、それともSpring-DAOの新しい名前ですか?

95
Pat

ここに、言及された各テクノロジーの紹介があります。

Spring-DAO

Spring-DAOは、厳密なスプリングモジュールではなく、DAOを記述し、適切に記述するように指示する規則です。そのため、データにアクセスするためのインターフェイスも実装もテンプレートも提供しません。 DAOを作成するときは、@Repositoryアノテーションを付けて、基盤となるテクノロジー(JDBC、Hibernate、JPAなど)にリンクされた例外が適切なDataAccessExceptionサブクラスに一貫して変換されるようにする必要があります。

例として、現在Hibernateを使用しており、サービス層がそれに反応するためにHibernateExceptionをキャッチするとします。 JPAに変更しても、DAOインターフェースは変更されず、サービスレイヤーはHibernateExceptionをキャッチするブロックでコンパイルされますが、DAOがJPA PersistenceExceptionをスローするため、これらのブロックを入力することはありません。 DAOで@Repositoryを使用すると、基盤となるテクノロジーにリンクされた例外がSpring DataAccessExceptionに変換されます。サービス層はこれらの例外をキャッチし、永続化テクノロジーを変更することにした場合、Springがネイティブ例外を変換したため、同じSpring DataAccessExceptionsが引き続きスローされます。

ただし、これには次の理由で使用が制限されていることに注意してください。

  1. プロバイダーがトランザクションをロールバックしている可能性があるため(通常、例外サブタイプに応じて)、永続性例外をキャッチしないでください。したがって、代替パスで実行を継続しないでください。
  2. 通常、例外の階層は、Springが提供するものよりもプロバイダーで豊富であり、1つのプロバイダーから他のプロバイダーへの明確なマッピングはありません。これに依存することは危険です。ただし、スキャン手順によってBeanが自動的に追加されるため、DAOに@Repository注釈を付けることをお勧めします。さらに、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はJdbcDaoSupportも提供します。これは、DAOを開発するために拡張できます。基本的に、2つのプロパティを定義します。DAOメソッドを実装するために使用できるDataSourceとJdbcTemplateです。また、SQL例外からSpring DataAccessExceptionsへの例外トランスレーターも提供します。

プレーンjdbcを使用する場合、これは使用する必要があるモジュールです。

Spring-ORM

Spring-ORMは、JPA、JDO、Hibernate、iBatisなどの多くの永続化テクノロジーをカバーする包括的なモジュールです。これらのテクノロジーのそれぞれについて、Springは統合クラスを提供するため、各テクノロジーはSpringの構成原則に従って使用でき、Springトランザクション管理とスムーズに統合できます。

各テクノロジーの構成では、基本的に、DataSource Beanを何らかのSessionFactoryまたはEntityManagerFactoryなどのBeanに注入します。 JDBCはDataSourceのみに依存するため、純粋なJDBCの場合、そのような統合クラス(JdbcTemplateを除く)は必要ありません。

JPAやHibernateなどのORMを使用する場合、spring-jdbcは必要ありませんが、このモジュールのみが必要です。

Spring-Data

Spring-Dataは、一般的な方法でデータ(DAO +注釈)にアクセスする方法を定義する共通のAPIを提供する包括的なプロジェクトで、SQLとNOSQLの両方のデータソースを対象としています。

最初のアイデアは、開発者がDAO(Finderメソッド)とエンティティクラスのインターフェイスをテクノロジに依存しない方法で記述し、構成のみに基づいて(DAOとエンティティ+スプリング構成のアノテーションで)テクノロジを提供することですxmlベースまたはJavaベース)、JPA(SQL)またはredis、hadoopなど(NOSQL)の実装テクノロジを決定します。

Finderのメソッド名に対してspringによって定義された命名規則に従う場合、最も単純な場合にはFinderのメソッドに対応するクエリ文字列を提供する必要さえありません。他の状況では、Finderメソッドの注釈内にクエリ文字列を提供する必要があります。

アプリケーションコンテキストが読み込まれると、springは、データアクセステクノロジに関連するすべての定型コードを含むDAOインターフェイスのプロキシを提供し、構成されたクエリを呼び出します。

Spring-Dataは非SQLテクノロジーに重点を置いていますが、JPA(唯一のSQLテクノロジー)のモジュールを提供しています。

次のステップ

これをすべて知ったので、次に何を選ぶかを決める必要があります。ここでの良いニュースは、あなたが技術のための決定的な最終選択をする必要がないということです。これは実際、Springの力が宿る場所です。開発者として、コードを書くときはビジネスに集中します。うまくやれば、基盤となるテクノロジーの変更は実装または構成の詳細になります。

  1. エンティティのPOJOクラスを使用してデータモデルを定義し、エンティティの属性と他のエンティティとの関係を表すメソッドを取得/設定します。テクノロジーに基づいてエンティティクラスとフィールドに注釈を付ける必要がありますが、現時点では、POJOで十分です。今のところ、ビジネス要件に集中してください。
  2. DAOのインターフェイスを定義します。 1つのDAOは1つのエンティティを正確にカバーしますが、関係をナビゲートすることで追加のエンティティをロードできるはずなので、それらのそれぞれにDAOは必要ありません。厳密な命名規則に従ってFinderメソッドを定義します。
  3. これに基づいて、他の誰かがDAOのモックを使用して、サービス層で作業を開始できます。
  4. さまざまな永続化テクノロジー(sql、no-sql)を学習して、ニーズに最適なものを見つけ、そのうちの1つを選択します。これに基づいて、エンティティに注釈を付け、DAOを実装します(または、spring-dataを使用することを選択した場合、スプリングにエンティティを実装させます)。
  5. ビジネス要件が進化し、データアクセステクノロジーがそれをサポートするのに十分でない場合(たとえば、JDBCといくつかのエンティティで始めたが、より豊富なデータモデルが必要であり、JPAがより良い選択である場合)、実装を変更する必要がありますDAOの場合、エンティティにいくつかの注釈を追加し、スプリング構成を変更します(EntityManagerFactory定義を追加します)。ビジネスコードの残りの部分には、変更による他の影響が表示されません。

注:トランザクション管理

Springは、トランザクション管理用のAPIを提供します。データアクセスにspringを使用する予定がある場合は、トランザクション管理にもspringを使用する必要があります。これらは非常にうまく統合されているためです。 Springがサポートする各データアクセステクノロジーには、ローカルトランザクションに対応するトランザクションマネージャーがあります。分散トランザクションが必要な場合は、JTAを選択できます。それらはすべて同じAPIを実装しているため、テクノロジの選択は、ビジネスコードにそれ以上影響を与えずに変更できる構成だけです。

注:Springのドキュメント

あなたが言及したSpringのドキュメントへのリンクはかなり古いものです。最新リリース(4.1.6、すべてのトピックを網羅)のドキュメントは次のとおりです。

Spring-dataはSpringフレームワークの一部ではありません。原則に慣れるために最初に読むべき共通モジュールがあります。ドキュメントは次の場所にあります。

151
Gaetan

Spring DAODataAccessObject):JDBC実装への抽象インターフェースを提供するオブジェクトフレームワーク、つまりSpring DAOは、個別のサポートクラスを使用してJDBCとHibernate、MyBatis、JPA、JDOにアクセスするためのgeneralizedコンセプトです。また、@Repositoryアノテーションを定義することにより、generalized例外階層を提供します。このアノテーションは、 SQL例外変換 から SQLException からSpringのデータアクセス戦略のためにSpringコンテナに定義します-不可知 DataAccessException 階層。

つまり、プラットフォーム固有の例外はキャッチであり、Springの未チェックのデータアクセス例外の1つとして再スローされます。


Spring JDBC:このモジュールを使用します。このモジュールは、DataSourceと、JdbcTemplateNamedParameterJdbcTemplate(wraps JdbcTemplate)、およびSimpleJdbcTemplateのようなテンプレートクラスのみに依存しますクロスカッティングの懸念。

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>

Spring JDBCは、拡張するJdbcDaoSupportNamedParameterJdbcDaoSupportSimpleJdbcDaoSupportも提供します。これらはsupport(ieconvenient)方法ですそして、独自の 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を簡単に統合できます。

  • Hibernateの場合はSessionFactory
  • JPAの場合はEntityManagerFactory
  • MyBatisのSqlSessionFactory
3
Premraj

SomeObjectDaoのようなインターフェイスを作成してから、JdbcSomeObjectDaoHibernateSomeObjectDaoのようなこのインターフェイスの異なる実装を作成します。次に、SomeObjectServiceクラスでSomeObjectDaoインターフェイスを操作し、そこに具体的な実装の1つを挿入します。したがって、SomeObjectDaoの各実装は、JDBCを使用するかORMを使用するかに関係なく、詳細を隠します。

通常、JDBC、およびORMのさまざまな実装は、さまざまな種類の例外をスローします。 SpringのDAOサポートは、これらの異なる技術固有の例外を一般的なSpring DAO例外にマッピングできます。したがって、実際の実装からさらに切り離されます。また、SpringのDAOサポートは、DAO開発でさらに役立つ抽象*DataSupportクラスのセットを提供します。したがって、SomeObjectDaoインターフェイスを実装する以外に、Springの*DataSupportクラスの1つを拡張できます。

0
mike_m

Spring-dao libはバージョン2.0.8(2008年1月)で停止しました。 spring-daoのクラスは、spring-txにコピーされました。したがって、spring-daoにあるクラスが必要な場合は、代わりに spring-tx に依存関係を追加してください。 ( ソース 。)

0
Paulo Merson

追加情報として。 Spring Data 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は、エンティティまたはDTO pojoにリンクされたSpringプロジェクションです。

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

  String getContractNumber();

  String getExecutiveNumber();
0
Brandon Osorio