1

私はSpringの世界ではまったく新しく、SpringとHibernateを統合するDAOを開発しようとしています。作業中のプロジェクトを作成しましたが、それについて建築上の疑問があります。

次のスタンドアロンの Hibernate チュートリアルに基づいて、Spring + Hibernate プロジェクトを作成しました (Spring や他のフレームワークを使用しないためスタンドアロンであり、単純な Java + Hibernate プロジェクトです): http://www.tutorialspoint.com/hibernate /hibernate_examples.htm

私のプロジェクトでは、必要なすべての CRUD メソッドを定義するインターフェイスと、このインターフェイスの具体的な実装があります。これは私の具体的なクラスのコードです。

package org.andrea.myexample.HibernateOnSpring.dao;

import java.util.List;

import org.andrea.myexample.HibernateOnSpring.entity.Person;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
import org.springframework.transaction.annotation.Transactional;

public class PersonDAOImpl implements PersonDAO {

    // Factory per la creazione delle sessioni di Hibernate:
    private static SessionFactory sessionFactory;

    // Metodo Setter per l'iniezione della dipendenza della SessionFactory:
    public void setSessionFactory(SessionFactory sessionFactory) {
        this.sessionFactory = sessionFactory;
    }

    /** CREATE CRUD Operation:
     * Aggiunge un nuovo record rappresentato nella tabella rappresentato
     * da un oggetto Person
     */
    @Transactional(readOnly = false)
    public Integer addPerson(Person p) {

        System.out.println("Inside addPerson()");

        Session session = sessionFactory.openSession();

        Transaction tx = null;
        Integer personID = null;

        try {
            tx = session.beginTransaction();

            personID = (Integer) session.save(p);
            tx.commit();
        } catch (HibernateException e) {
            if (tx != null)
                tx.rollback();
            e.printStackTrace();
        } finally {
            session.close();
        }

        return personID;

    }

    // READ CRUD Operation (legge un singolo record avente uno specifico id):
    public Person getById(int id) {

        System.out.println("Inside getById()");

        Session session = sessionFactory.openSession();

        Transaction tx = null;          
        Person retrievedPerson = null;  

        try {
            tx = session.beginTransaction();
            retrievedPerson = (Person) session.get(Person.class, id);
            tx.commit();
        }catch (HibernateException e) { 
            if (tx != null)                 
                tx.rollback();          
            e.printStackTrace();
        } finally {                 
            session.close();
        }

        return retrievedPerson;
    }

    // READ CRUD Operation (recupera la lista di tutti i record nella tabella):
    @SuppressWarnings("unchecked")
    public List<Person> getPersonsList() {

        System.out.println("Inside getPersonsList()");

        Session session = sessionFactory.openSession();
        Transaction tx = null;
        List<Person> personList = null;

        try {
            tx = session.beginTransaction();
            Criteria criteria = session.createCriteria(Person.class);
            personList = criteria.list();
            System.out.println("personList: " + personList);
            tx.commit();
        }catch (HibernateException e) { 
            if (tx != null)                 
                tx.rollback();          
            e.printStackTrace();
        } finally {
            session.close();
        }
        return personList;
    }

    // DELETE CRUD Operation (elimina un singolo record avente uno specifico id):
    public void delete(int id) {

        System.out.println("Inside delete()");

        Session session = sessionFactory.openSession();
        Transaction tx = null;

        try {
            tx = session.beginTransaction();
            Person personToDelete = getById(id);
            session.delete(personToDelete);
            tx.commit();
        }catch (HibernateException e) { 
            if (tx != null)                 
                tx.rollback();          
            e.printStackTrace();
        } finally {
            session.close();
        }

    }

    @Transactional
    public void update(Person personToUpdate) {

        System.out.println("Inside update()");

        Session session = sessionFactory.openSession();
        Transaction tx = null;

        try {
            System.out.println("Insite update() method try");
            tx = session.beginTransaction();
            session.update(personToUpdate);

            tx.commit();
        }catch (HibernateException e) { 
            if (tx != null)                 
                tx.rollback();          
            e.printStackTrace();
        } finally {
            session.close();
        }   

    }

}

1) 最初の疑問は、このクラスでは、CRUD メソッドごとに新しいセッションを開くという事実に関連しています。

このチュートリアルでは、 http://www.tutorialspoint.com/hibernate/hibernate_sessions.htmを読んだので、私はこのようにしました:

Session オブジェクトは軽量で、データベースとの対話が必要になるたびにインスタンス化されるように設計されています。永続オブジェクトは、Session オブジェクトを介して保存および取得されます。通常、セッション オブジェクトはスレッド セーフではなく、必要に応じて作成および破棄する必要があるため、セッション オブジェクトを長時間開いたままにしないでください。

しかし、Spring と Hibernate を統合することで、各 CRUD メソッドで新しいセッションを開く必要はないと誰かが私に言いました。@Transactional アノテーションをすべての CRUD メソッドに追加する、Spring によって現在のトランザクションに関連付けられているセッションこれも、トランザクションの終了時に Spring によってクローズされます。トランザクションが開閉されるたびにセッションを開閉するのはSpringです。

したがって、それが本当なら、セッションを 1 回だけ開いて、現在のセッションを取得する必要があります。

それは本当ですか、それとも私の具象クラスは正しいですか(うまく機能しますが、愚かな方法で機能するかどうかはわかりません!!!)

2) 2 番目の疑問は、Spring のドキュメントを読むという事実に関連しています。 orm-hibernate DAO を順番に呼び出す AOP サービスを使用していることがわかります...

それで...私のアーキテクチャはとても悪いですか?DAO と Hibernate を使用して DAO を実装する具象クラスを rappresent するインターフェイスがあり、そのメソッドを呼び出して DB で CRUD 操作を行います

4

1 に答える 1

5

#1について。@Transactionalはい、DAO の CRUD 操作メソッドでアノテーションを使用する場合、セッションの開閉を明示的に処理する必要はありません。春はあなたのためにそれをします。内部で行う必要があるのは、現在のセッションで CRUD メソッドを呼び出すことだけです。これは、 を呼び出すことによって取得されsessionFactory.getCurrentSession()ます。上記のコードで行ったように、トランザクションを明示的に開いてコミットし、ロールバックする必要はありません。メソッドに で注釈を付けると、Spring がそれを行います@Transactional

#2について。Spring には、DAO 実装に到達する独自の方法があります。AOPを使用している可能性があります。それはあなたのアーキテクチャが間違っているという意味ではありません。インターフェイスと具象クラスの実装を使用するアーキテクチャは、正しい方法です。私がすることは、基本クラスによって実装されたすべての CRUD 操作を作成し、サブクラスに DAO 固有のメソッドを実装させることです。私が意味したのはこれです(疑似コードのみを提供します):

interface BaseDAO {//declare all the CRUD methods}

interface PersonaDAO extends BaseDAO {//declare all Person related methods like getPersonsList}

class BaseDAOImpl implements BaseDAO {//CRUD method implementations }

class PersonaDAOImpl extends BaseDAOImpl implements PersonDAO {//implementation of Person related methods}

これは、CRUD 操作コードを再利用できるように、より優れたアーキテクチャになると思います。お役に立てれば。

于 2013-03-09T08:10:09.697 に答える