Spring事务注解

8

我希望能更好地理解Spring的@Transactional属性的使用。我明白它基本上在被标记为@Transactional的方法内容中包装了一个事务。将服务/业务层方法标记为事务处理是否合适,而不是像我在这里所做的那样标记实际的DAO方法?

服务实现

public class UserServiceImpl implements UserServiceInt{
   @Autowired
   private UserServiceDAO serviceDAO;


   @Override
   public User getUser(int id){
      return serviceDAO.getUser(id);
   }

   @Override
   @Transactional
   public void updateUserFirstName(int id, String firstName) throws SomeException{
      User userToUpdate = getUser(id);
      if(userToUpdate == null){
         throw new SomeException("User does not exist");
      }
      userToUpdate.setFirstName(firstName);
      serviceDAO.updateUser(userToUpdate);
   }

}

DAO实现

public class UserServiceDAOImpl implements UserServiceDAOInt{
   @PersistenceContext(unitName="myUnit")
   private EntityManager entityManager;

   @Override
   public void updateUser(User user){
      entityManager.merge(user);
   }

}

我甚至不确定调用 merge 方法是否必要。由于 UserServiceImpl 类中没有声明 EntityManager,Spring 如何知道该使用哪个 EntityManager?


是的,将您的服务或服务方法注释为@Transactional是合适的 - 例如,如果服务跨越多个DAO。此外,您是正确的,您不必显式调用merge。用户对象已经与持久性上下文相关联(通过调用get()),并且在事务结束时其状态与DB同步。Merge用于更新在事务之外更改的对象。 - Ori Dar
虽然这与你的问题有些偏离,但你可能会发现它很相关。请查看http://projects.spring.io/spring-data-jpa/,它可以帮助你减少DAO层中的大量样板代码。 - Đuro
请查看这里我的回答,或许能帮到你http://stackoverflow.com/questions/30490924/what-data-is-stored-in-transaction/30494434#30494434 - jgr
1个回答

6

当Service类中的方法有多个数据库调用时,如果我们想要所有调用都发生或者所有调用都不发生,或者说如果任何一个调用失败,则整个事务都应该回滚,此时我们会使用@Transactional来标记Service层。如果我们不符合这个条件,则可以在DAO层上选择@Transactional

Spring如何知道要使用哪个EntityManager,因为UserServiceImpl类中没有声明EntityManager?

Spring是从classpath下的引用EntityManager的,其结构类似于以下内容:

<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd" version="1.0">
    <persistence-unit name="myUnit">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <jta-data-source>java:/YourDatasource</jta-data-source>

        <properties>
            <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/>
            <property name="hibernate.hbm2ddl.auto" value="update" />
            <property name="hibernate.show_sql" value="true" />
        </properties>
    </persistence-unit>
</persistence>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接