Подтвердить что ты не робот

Некоторое разъяснение в отношении аннотации Spring @Transactional по методу

Я совершенно новый в мире Spring, и я разработал простой проект, который использует Spring 3.2.1 и Hibernate 4.1.9 для реализации DAO. Проект работает правильно, но у меня есть некоторые сомнения в использовании аннотации @Transactional Spring для метода CRUD этого DAO.

Это весь код класса, реализующего операцию 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 должно иметь семантику транзакций, но что это означает с транзакционной семантикой?

Это означает, что выполнение methos должно рассматриваться как исполнение транзакции? Таким образом, это означает, что операции метода должны рассматриваться как одна операция, которая может привести к успеху или неудаче, если результаты успешны, результаты операций должны быть постоянными, тогда как в случае отказа вернуться в состояние до начало транзакции.

Это смысл использования аннотации @Transactional для метода?

И что именно означает атрибут readOnly = false в аннотации @Transactional метода addPerson()? это значит, что я могу написать запись в базе данных (и не только прочитать ее), или что? Сомнение связано с тем, что я понимаю, что по умолчанию транзакция, определенная с использованием @Transactional annotaion, чтение/запись, а не просто чтение... Я также пытаюсь удалить атрибут (readOnly = false) и все еще хорошо работать (вставьте новую запись в таблицу базы данных)

Следующий dout: "почему какой-то метод аннотируется с использованием аннотации @Transactional, а некоторые другие методы нет? является ли это хорошей оценкой, чтобы аннотировать метод ALL CRUD? @Transactional?"

Тпх

Andrea

4b9b3361

Ответ 1

Прежде всего, вы не должны делать методы DAO транзакционными, но сервисными методами.

Во-вторых, использование Transactional - это способ позволить Spring запускать и совершать/откатывать транзакции для вас. Поэтому вы не должны запускать и совершать транзакции самостоятельно.

В-третьих: это будет работать, только если вы используете диспетчер транзакций, который знает, как связать сеанс Hibernate с транзакцией (как правило, HibernateTransactionManager). Сеанс factory также должен обрабатываться Spring и вводиться Spring в ваши DAO. Код DAO должен выглядеть следующим образом:

В-четвертых: вы не должны открывать новый сеанс, но получать текущий, связанный с текущей транзакцией, 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);
    }
}

Для получения дополнительной информации прочитайте документацию.