Spring DAO対Spring ORM対Spring JDBC


103

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

私が理解しているように、Spring JDBCには、従来の方法でデータベースにアクセスするための定型コードを削減するためのテンプレートが用意されています。つまり、独自のSQLクエリを記述します。

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

SpringのウェブサイトによるSpring-DAO:

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

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

誰もがこれらの3つの間の違いを正確に何を明確にしてくれますか?どのシナリオでどちらを優先すべきですか?

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

回答:


162

ここでは、前述の各テクノロジーの概要を示します。

春だお

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

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

ただし、次の理由により、これには使用制限があります。

  1. プロバイダーは(正確な例外サブタイプに応じて)トランザクションをロールバックした可能性があるため、通常は永続化例外をキャッチしないでください。したがって、代替パスで実行を継続しないでください。
  2. 例外の階層は通常、Springが提供するものよりもプロバイダーで豊富であり、プロバイダー間での明確なマッピングはありません。これに依存することは危険です。ただし@Repository、Beanはスキャン手順によって自動的に追加されるため、DAOにで注釈を付けることをお勧めします。さらに、Springは他の便利な機能を注釈に追加する場合があります。

Spring-JDBC

Spring-JDBCが提供するJdbcTemplateクラスは、配管コードを削除し、SQLクエリとパラメーターに集中するのに役立ちます。あなたはそれをで構成する必要があるだけ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、いくつかの種類に豆をSessionFactory、またはEntityManagerFactory等ビーン。純粋なJDBCの場合、JDBCはDataSourceにのみ依存するため、JdbcTemplateを除いて、そのような統合クラスは必要ありません。

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

春のデータ

Spring-Dataは、より一般的な方法でデータ(DAO +注釈)にアクセスする方法を定義するための共通APIを提供する包括的なプロジェクトであり、SQLおよびNOSQLデータソースの両方をカバーします。

最初のアイデアは、開発者がDAO(ファインダーメソッド)とエンティティクラスのインターフェイスをテクノロジにとらわれない方法で記述し、構成のみ(DAOとエンティティの注釈+ Spring構成に基づく)に基づいてテクノロジを提供することですxml-またはjava-based)は、JPA(SQL)、redis、hadoopなど(NOSQL)の実装テクノロジを決定します。

finderメソッド名について、springによって定義された命名規則に従う場合、最も単純なケースでは、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)を学習してニーズに最適なものを見つけ、それらの1つを選択します。これに基づいて、エンティティに注釈を付けてDAOを実装します(または、spring-dataの使用を選択した場合は、Springにエンティティを実装させます)。
  5. ビジネス要件が進化し、データアクセステクノロジーがそれをサポートするのに十分でない場合(たとえば、JDBCといくつかのエンティティから始めたが、より豊富なデータモデルが必要であり、JPAがより適切な選択肢である場合)、実装を変更する必要があります。 DAOのいくつかのアノテーションをエンティティに追加し、Spring構成を変更します(EntityManagerFactory定義を追加します)。ビジネスコードの残りの部分には、変更による他の影響はありません。

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

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

注:Springのドキュメント

あなたが言及したSpringのドキュメントへのリンクはかなり古いです。以下は最新リリースのドキュメントです(4.1.6、すべてのトピックをカバー):

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


私はこの回答(Spring Dataなど)の一部の説明で「アンブレラ」という用語を使用して、(傘がよりドメイン固有であるのではなく)サブコンポーネント/モジュールが存在することを示して感謝しています。また、Spring Dataについて言及することは、質問では言及されていませんが、ここでは非常に役立ちます。
cellepo

しないspring-jdbcここでは言及していない他の有用なツールを提供して?たとえばSimpleJdbcInsert、単一エントリの挿入と一括処理(もちろん、妥当な規模まで)の両方に非常にクリーンで便利です。
Nom1fan

3

Spring DAOD ata A ccess O bject):JDBC実装フレームワークへの抽象インターフェースを提供するオブジェクトです。つまり、Spring DAOは 、JDBCとHibernate、MyBatis、JPA、JDOにアクセスするための一般化された概念であり、個々のサポートクラスを使用します。また、アノテーションを定義することにより、一般化された例外階層を提供します@Repository。このアノテーションは、Spring のデータアクセス戦略にとらわれない 階層からSQLへのSQL例外変換のためのSpringコンテナを定義します。 SQLExceptionDataAccessException

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


Spring JDBC:プレーンJDBCの場合、このモジュールを使用します。これは、や(wraps )などのDataSourceテンプレートクラスにのみ依存しておりJdbcTemplate、横断的な懸念を減らすために使用します。 NamedParameterJdbcTemplateJdbcTemplateSimpleJdbcTemplate

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も提供し JdbcDaoSupportNamedParameterJdbcDaoSupportSimpleJdbcDaoSupportである、サポート(つまり、便利な当社独自の拡張と発展させる)方法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し、その後のように、このインタフェースの異なる実装を作成しJdbcSomeObjectDaoHibernateSomeObjectDao。次に、SomeObjectServiceクラスでSomeObjectDaoインターフェイスを操作し、そこに具体的な実装の1つを注入します。したがってSomeObjectDao、JDBCを使用してもORMを使用しても、の各実装は詳細を隠します。

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


つまり、Spring-daoはHibernate / JDO / JDBCに固有の例外を抽象化し、例外の標準セットを提供しますか?それがいずれかを持っていtemplatesたアクセスデシベルに?それとも他のSpringコンポーネントで使用される抽象化ですか?たとえば、spring-daoのみを使用してdbにアクセスするコードを作成することは可能ですか(spring-jdbc、spring-orm、hibernateまたはその他のフレームワークを使用せずに)?
Pat

0

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

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

  String getContractNumber();

  String getExecutiveNumber();

1
コードを読みやすいようにコードブロックでフォーマットしてください。
特定のパフォーマンス2018
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.