本文介绍了关于 Spring @Transactional 在方法上的注解的一些说明的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我是 Spring 世界的新手,我开发了一个使用 Spring 3.2.1 和 Hibernate 4.1.9 来实现 DAO 的简单项目.该项目工作正常,但我对在此 DAO 的 CRUD 方法上使用 @Transactional Spring 注释有一些疑问.

I am quite new in Spring world and I have developed a simple project that use Spring 3.2.1 and Hibernate 4.1.9 to implement a DAO. The project work correctly but I have some doubts about the use of @Transactional Spring annotation on CRUD method of this DAO.

这是实现我项目CRUD操作的类的全部代码:

This is the entire code of the class that implement the CRUD operation of my project:

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 注解.

Ok,as you can see some methods are annoted using @Transactional annotation.

我在这里阅读官方文档http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/transaction.html 关于在方法上使用这个注解,它看到:使用@Transactional 注释的方法必须具有事务语义,但事务语义意味着什么?

I am readin the official documentation here http://static.springsource.org/spring/docs/3.2.x/spring-framework-reference/html/transaction.html about the use of this annotation on methods and it see that: A method annoted using @Transactional must have transactional semantics but what it means with transactional semantics?

这意味着methos执行必须被视为交易的执行?所以这意味着方法操作必须被视为可能导致成功或失败的单个操作,如果成功,操作的结果必须是永久的,而如果失败,则返回之前的状态交易的开始.

It means that the methos execution has to be considered as the execution of a transaction? So it means that the method operations have to be considered as a single operation that which may lead to a success or a failure, if successful, the results of operations has to be permanent, whereas in case of failure to return to the state prior to the start of the transaction.

这是在方法上使用 @Transactional 注释的含义吗?

Is this the meaning of use @Transactional annotation on a method?

addPerson() 方法的 @Transactional 注释中的 readOnly = false 属性究竟是什么意思?这意味着我还可以在数据库中写入一条记录(而不仅仅是读取它)还是什么?疑问是相关的,因为我知道,默认情况下,使用@Transactional annotaion 定义的事务是读/写,而不仅仅是读...我也尝试删除 (readOnly = false) 属性,但仍然运行良好(在数据库表中插入新记录)

And what exactly mean the readOnly = false attribute in the @Transactional annotation of the addPerson() method? it mean that I can also write a record in the database (and not only read it) or what? The doubt is related because I have understand that, by default, a transaction definied using @Transactional annotaion is read/write and not just read...I have also try to delete the (readOnly = false) attribute and still work well (insert the new record in the database table)

以下内容是:为什么有些方法使用@Transactional 注释而其他一些方法不使用?使用@Transactional 注释所有 CRUD 方法是一个好习惯吗?"

The following dout is: "why some method are annoted using @Transactional annotation and some other methods not? is it a good pratcice to annote ALL CRUD method withd @Transactional?"

Tnx

安德里亚

推荐答案

首先,你不应该让 DAO 方法成为事务性的,而是服务方法.

First of all, you shouldn't make DAO methods transactional, but service methods.

其次,使用 Transactional 是让 Spring 为您启动和提交/回滚事务的一种方式.所以你不应该自己开始和提交事务.

Second, using Transactional is a way to let Spring start and commit/rollback transactions for you. So you shouldn't start and commit transactions yourself.

第三:这仅在您使用知道如何将 Hibernate 会话与事务相关联的事务管理器(通常为 HibernateTransactionManager)时才有效.会话工厂也应该由 Spring 处理,并由 Spring 注入到您的 DAO 中.DAO 的代码应该是这样的:

Third: this will only work if you use a transaction manager that knows how to associate a Hibernate session with the transaction (typically, a HibernateTransactionManager). The session factory should also be handled by Spring, and injected by Spring in your DAOs. The code of the DAO should look like this:

第四:您不应该打开一个新会话,而是获取当前会话,由 Spring 关联到当前事务.

Fourth: you should not open a new session, but get the current one, associated to the current transaction by 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);
    }
}

阅读 文档 了解更多信息.

Read the documentation for more information.

这篇关于关于 Spring @Transactional 在方法上的注解的一些说明的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

07-23 09:39