我在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的代码应如下所示:
HibernateTransactionManager
第四:您不应该打开一个新会话,而是要获取一个与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); } }
阅读文档以获取更多信息。