41

私はSpringの世界ではまったく新しいので、Spring3.2.1とHibernate4.1.9を使用してDAOを実装する簡単なプロジェクトを開発しました。プロジェクトは正しく機能しますが、このDAOのCRUDメソッドで@TransactionalSpringアノテーションを使用することに疑問があります。

これは、私のプロジェクトの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();
        }   

    }

}

ご覧のとおり、いくつかのメソッドは@Transactionalアノテーションを使用してアノテーションが付けられています。

メソッドでのこのアノテーションの使用については、http: //static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/transaction.htmlの公式ドキュメントを読んでいます。 @Transactionalを使用してアノテーションが付けられたメソッドは、トランザクションセマンティクスを持っている必要がありますが、トランザクションセマンティクスとはどういう意味ですか?

これは、メトスの実行をトランザクションの実行と見なす必要があることを意味しますか?つまり、メソッド操作は、成功または失敗につながる可能性のある単一の操作と見なす必要があります。成功した場合、操作の結果は永続的である必要がありますが、失敗した場合は、以前の状態に戻ることができません。トランザクションの開始。

これは、メソッドで@Transactionalアノテーションを使用することの意味ですか?

そして、 addPerson()メソッドの@TransactionalアノテーションのreadOnly = false属性とは正確にはどういう意味ですか?それは、データベースにレコードを書き込むこともできる(そしてそれを読み取るだけではない)ことを意味しますか?デフォルトでは、@ Transactional注釈を使用して定義されたトランザクションは読み取り/書き込みであり、読み取りだけではないことを理解しているため、疑問が関連しています... (readOnly = false)属性を削除しようとしても、正常に機能します(挿入データベーステーブルの新しいレコード)

次のように、「@ Transactionalアノテーションを使用してアノテーションが付けられているメソッドと、そうでないメソッドがあるのはなぜですか?@Transactionalを使用してALL CRUDメソッドにアノテーションを付けるのは良い習慣ですか?」

Tnx

アンドレア

4

2 に答える 2

76

まず、DAOメソッドをトランザクションにするのではなく、サービスメソッドにする必要があります。

次に、Transactionalを使用すると、Springでトランザクションを開始し、コミット/ロールバックすることができます。したがって、自分でトランザクションを開始してコミットするべきではありません。

3番目:これは、Hibernateセッションをトランザクション(通常は)に関連付ける方法を知っているトランザクションマネージャーを使用する場合にのみ機能しますHibernateTransactionManager。セッションファクトリもSpringによって処理され、DAOにSpringによって注入される必要があります。DAOのコードは次のようになります。

4番目:新しいセッションを開くのではなく、Springによって現在のトランザクションに関連付けられている現在のセッションを取得する必要があります。

public class PersonDAOImpl implements PersonDAO {

    @Autowired
    private SessionFactory sessionFactory;

    public Integer addPerson(Person p) {
        Session session = sessionFactory.getCurrentSession();
        Integer personID = (Integer) session.save(p);
        return personID;
    }

    public Person getById(int id) {
        Session session = sessionFactory.getCurrentSession();
        Person retrievedPerson = (Person) session.get(Person.class, id);
        return retrievedPerson;
    }

    @SuppressWarnings("unchecked")
    public List<Person> getPersonsList() {
        Session session = sessionFactory.getCurrentSession();
        Criteria criteria = session.createCriteria(Person.class);
        return criteria.list();
    }

    public void delete(int id) {
        Session session = sessionFactory.getCurrentSession();
        Person personToDelete = getById(id);
        session.delete(personToDelete);
    }

    public void update(Person personToUpdate) {
        Session session = sessionFactory.getCurrentSession();
        session.update(personToUpdate);
    }
}

詳細については、ドキュメントをお読みください。

于 2013-03-08T18:19:51.053 に答える