1. 概要

この記事では、DAOをSpringとHibernate実装する方法を説明します。 コアHibernate構成については、以前の Hibernate 5 withSpringの記事を確認してください。

2. これ以上の春のテンプレートはありません

Spring3.0およびHibernate3.0.1以降、Hibernateセッションを管理するためにSpringHibernateTemplateは不要になりましたコンテキストセッション Hibernate によって直接管理され、トランザクションのスコープ全体でアクティブなセッションを利用できるようになりました。

結果として、HibernateTemplateの代わりにHibernateAPIを直接使用することがベストプラクティスになりました。これにより、DAOレイヤーの実装がSpringから完全に切り離されます。

2.1. HibernateTemplateなしの例外変換

例外変換は、 HibernateTemplate の責任の1つであり、低レベルのHibernate例外をより高レベルの一般的なSpring例外に変換します。

テンプレートがない場合でも、このメカニズムは有効であり、@Repositoryアノテーションが付けられたすべてのDAOに対してアクティブです。 内部的には、これはすべての @RepositoryBeanにSpringコンテキストで見つかったすべてのPersistenceExceptionTranslatorを通知するSpringBeanポストプロセッサーを使用します。

覚えておくべきことの1つは、例外変換ではプロキシが使用されるということです。 SpringがDAOクラスの周りにプロキシを作成できるようにするには、これらをfinalとして宣言してはなりません。

2.2. テンプレートを使用しないHibernateセッション管理

コンテキストセッションのHibernateサポートが発表されたとき、HibernateTemplateは本質的に廃止されました。 実際、このクラスのJavadocは、この側面を強調しています(元の部分から太字になっています)。

注:Hibernate 3.0.1以降、トランザクションHibernateアクセスコードはプレーンなHibernateスタイルでコーディングすることもできます。 したがって、新しく開始されたプロジェクトでは、{@ link org.hibernate.SessionFactory#getCurrentSession()}に基づいて、代わりに標準のHibernate3スタイルのコーディングデータアクセスオブジェクトを採用することを検討してください。

3. DAO

まず、ベースDAOから始めます。これは、一般的な汎用操作をサポートし、エンティティごとに拡張できる、抽象化されたパラメーター化されたDAOです。

public abstract class AbstractHibernateDao<T extends Serializable> {
    private Class<T> clazz;

    @Autowired
    protected SessionFactory sessionFactory;

    public final void setClazz(final Class<T> clazzToSet) {
        clazz = Preconditions.checkNotNull(clazzToSet);
    }

    // API
    public T findOne(final long id) {
        return (T) getCurrentSession().get(clazz, id);
    }

    public List<T> findAll() {
        return getCurrentSession().createQuery("from " + clazz.getName()).list();
    }

    public T create(final T entity) {
        Preconditions.checkNotNull(entity);
        getCurrentSession().saveOrUpdate(entity);
        return entity;
    }

    public T update(final T entity) {
        Preconditions.checkNotNull(entity);
        return (T) getCurrentSession().merge(entity);
    }

    public void delete(final T entity) {
        Preconditions.checkNotNull(entity);
        getCurrentSession().delete(entity);
    }

    public void deleteById(final long entityId) {
        final T entity = findOne(entityId);
        Preconditions.checkState(entity != null);
        delete(entity);
    }

    protected Session getCurrentSession() {
        return sessionFactory.getCurrentSession();
    }
}

ここで興味深い点がいくつかあります。前述のように、抽象DAOはSpringテンプレート( HibernateTemplate など)を拡張しません。 代わりに、Hibernate SessionFactory はDAOに直接挿入され、公開されるコンテキスト Session を通じて、メインのHibernateAPIの役割を果たします。

this.sessionFactory.getCurrentSession();

また、コンストラクターは、エンティティの Class を、汎用操作で使用されるパラメーターとして受け取ることに注意してください。

ここで、このDAO の実装例を見てみましょう、 Fooエンティティの場合:

@Repository
public class FooDAO extends AbstractHibernateDAO< Foo > implements IFooDAO{

   public FooDAO(){
      setClazz(Foo.class );
   }
}

4. 結論

この記事では、HibernateとSpringを使用した永続層の構成と実装について説明しました。

DAOレイヤーのテンプレートへの依存をやめる理由と、トランザクションとHibernateセッションを管理するためにSpringを構成する際の落とし穴について説明しました。 最終的な結果は、Springにコンパイル時の依存がほとんどない、軽量でクリーンなDAO実装です。

この単純なプロジェクトの実装は、githubプロジェクトにあります。