当前位置: 首页 > 面试题库 >

关于方法上的Spring @Transactional注释的一些说明

东方旭东
2023-03-14
问题内容

我在Spring领域还很陌生,我开发了一个简单的项目,该项目使用Spring 3.2.1和Hibernate
4.1.9来实现DAO。该项目可以正常工作,但是我对在此DAO的CRUD方法上使用 @Transactional Spring批注有一些疑问。

这是实现我的项目的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注释所有CRUD方法是否是一个好习惯?”

特纳克斯

安德里亚


问题答案:

首先,您不应该使DAO方法具有事务性,而应使服务方法具有事务性。

其次,使用Transactional是让Spring为您启动和提交/回滚事务的一种方法。因此,您不应该自己启动和提交事务。

第三:仅当您使用知道如何将Hibernate会话与事务相关联的事务管理器(通常为a
HibernateTransactionManager)时,此方法才有效。会话工厂也应该由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);
    }
}

阅读文档以获取更多信息。



 类似资料:
  • 这是实现我的项目的CRUD操作的类的整个代码: 好的,正如您所看到的,使用@Transactional注释对一些方法进行了注释。 我正在阅读官方文档http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/transaction.html中关于该注释在方法上的使用,它看到了:使用@transac

  • 问题内容: 我在Service类中看到了一种被标记为的方法,但是它也在同一类中调用了其他未标为的方法。 这是否意味着对单独方法的调用导致应用程序打开与DB的单独连接或暂停父事务等? 不带任何注释的方法的默认行为是什么,而另一个带有注释的方法调用该方法的默认行为是什么? 问题答案: 当你调用没有事务块之内的方法时,父事务将继续使用新方法。它将使用与父方法(with )相同的连接,以及在调用的方法中导

  • 我正在使用带有webflux的spring boot 2.4.2连接到postgres数据库。我在使用事务性代码时观察到了一个我不理解的行为。 为了展示这种行为,我创建了一个示例应用程序,试图将行添加到两个表中;表“a”和表“b”。对表“a”的插入预计将失败,并出现重复密钥冲突。考虑到使用了事务性,我希望不会向表“b”中添加任何行。 然而,根据我用哪个方法注释事务,我会得到不同的结果。 如果我对c

  • 问题内容: 美好的一天。如下代码: 据我了解,如果方法中存在异常,则不会回滚事务。以及如何使它滚动?并返回SomeResult 问题答案: 您不应该以编程方式调用回滚。根据docs的建议,最好的方法是使用声明性方法。为此,您需要注释哪些异常将触发回滚。 在你的情况下,像这样 看一下@Transaction API 和有关回滚事务的文档。 如果尽管有文档建议,但仍要进行程序化回滚,则需要按照已建议的

  • 我正在学习Spring MVC Showcase项目,可从STS仪表板下载 我有以下情况,但我并不完全清楚: 我有以下表格: 与id="readForm"的表单的提交操作相关,我有以下Jquery函数,它简单地执行一个AJAX调用,将两个经过验证的文本变量隐藏在请求的主体字段中:**foo=bar和Fru=apple 我的控制器类处理此请求的方法如下: 好的,该方法将使用@ModelAttribu