kagamihogeの日記

kagamihogeの日記です。

Spring Framework Reference Documentation 4.1.xのV. Data Access 17. DAO supportをテキトーに訳した

http://docs.spring.io/spring/docs/current/spring-framework-reference/htmlsingle/#dao をテキトーに訳した。

17. DAO support

17.1 Introduction

SpringのData Access Object (DAO)サポートの目的は一貫性のある方法でJDBC, Hibernate, JPA, JDOなどのデータアクセス技術との組み合わせを容易にすることです。これにより前述の永続化技術の乗り換えを容易に行えるようになり、それぞれの技術に固有の例外キャッチなどに気を配るコードを書く必要もなくなります。

17.2 Consistent exception hierarchy

Springでは、SQLExceptionなど個々の技術に固有の例外を、ルート例外にDataAccessExceptionを持つ例外クラス階層へと、使いやすい形に変換します。この例外クラスはオリジナルの例外をラップするため、何らかのエラーが発生したことを示す情報を失うリスクはありません。

JDBCの例外に加え、SpringはHibernate固有の例外をラップし、プロプライエタリなチェック例外(Hibernate 3.0より前のHibenateの場合)をランタイム例外に変換します(同様なことがJDOとJPAの例外にも当てはまります)。これにより、良くありがちで回復不能な永続化の例外を、DAO等で例外宣言とcatch-and-throwブロックという面倒なボイラープレートを書くことなしに、適切なレイヤーで処理可能になります。(何らかの処理が必要な例外については依然として対処が必要です。)上述の通り、JDBC例外(DB固有のダイアレクト含む)も同じ階層に変換されるため、一貫性のあるプログラミングモデルでJDBCに対する操作が可能です。

上記と同様なことが、Springがサポートする各種ORMフレームワークのテンプレートに対して言えます。インターセプターベースのクラスを使う場合、アプリケーションはHibernateExceptionsJDOExceptionsの処理をする必要があり、可能であれば、それぞれSessionFactoryUtils’ `convertHibernateAccessException(..)もしくはconvertJdoAccessException()メソッドにデリゲートするのが望ましいです。これらのメソッドはその例外をorg.springframework.daoの例外階層に適合するように変換します。JDOExceptionsは未チェックなので単に再スローすることも可能なため、例外の観点では汎用的なDAO抽象化を犠牲にしていると言うことも出来ます。

Springが提供する例外階層を以下に示します。(以下の図のクラス階層はDataAccessExceptionのサブセットのみな点に注意してください。)

DataAccessException

17.3 Annotations used for configuring DAO or Repository classes

Data Access Objects (DAOs)やリポジトリが例外変換を行うよう保証する最良の方法は@Repositoryアノテーションを使うことです。このアノテーションにより、XML設定を書くことなく、DAOとリポジトリの発見と設定のためのコンポーネントスキャンが可能となります。

@Repository
public class SomeMovieFinder implements MovieFinder {
    // ...
}

DAOやリポジトリの実装は永続化リソースにアクセスする必要があり、永続化リソースは使用する永続化技術に依存します。たとえば、JDBCベースのリポジトリJDBCDataSourceにアクセスする必要があり、JPAベースのリポジトリEntityManagerにアクセスする必要があります。これを実現する最も簡単な方法は、@Autowired, @Inject, @Resource, @PersistenceContextなどで、リソースの依存性をDIすることです。以下はJPAリポジトリの例です。

@Repository
public class JpaMovieFinder implements MovieFinder {

    @PersistenceContext
    private EntityManager entityManager;

    // ...

}

クラシックなHibernate APIを使用する場合はSessionFactoryをDIします。

@Repository
public class HibernateMovieFinder implements MovieFinder {

    private SessionFactory sessionFactory;

    @Autowired
    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    // ...

}

最後のサンプルは一般的なJDBCのサポートです。DataSourceを使用するSimpleJdbcCallなどのデータアクセスサポートやJdbcTemplateを生成する初期化メソッドDataSourceをDIしています。

@Repository
public class JdbcMovieFinder implements MovieFinder {

    private JdbcTemplate jdbcTemplate;

    @Autowired
    public void init(DataSource dataSource) {
        this.jdbcTemplate = new JdbcTemplate(dataSource);
    }

    // ...

}

上記のアノテーションを利用するためのアプリケーションコンテキストの設定方法の詳細については個々の永続化技術のドキュメントを参照してください。