Spring 事务注解

问题描述 投票:0回答:2

我正在尝试更好地处理 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);
   }

}

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

java spring spring-mvc transactions entitymanager
2个回答
6
投票

当服务类中的方法有多个数据库调用时,我们用

@Transactional
标记服务层,并且我们希望所有调用都应该发生或者没有任何一个调用发生,或者我们可以说如果任何调用失败,那么整个事务应该
rollback
。如果我们不符合这个标准,那么我们也可以在 DAO 层上选择
@Transactional

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

Spring引用了

EntityManager
中的
persistence.xml
(来自类路径),其结构如下:

<?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>

0
投票

首先重要的是要看到,Spring 中有 2 种不同的 @Transactional 方法: JakartaEE 标准化:

import jakarta.transaction.Transactional;

Spring 专有:

import org.springframework.transaction.annotation.Transactional;

两者都有效,后一种为您提供更多选择。 @Transactional 由代理处理,该代理在运行时拦截对组件的所有调用。 Spring 将事务上下文保存在 ThreadLocal 变量中,这就是 Spring 确定调用(线程)属于哪个事务的方式。如果你不用自己创建的线程搞砸事情,一切都会好起来的。

回答你的问题:如果你只有存储库 @Transactional (Spring Jpa 存储库自动执行此操作),则对存储库的每个调用都将在其自己的事务中运行。

这篇文章很好地描述了事情是如何运作的: https://ciit-training.com/2024/01/06/transactional-in-spring-how-it-works/

© www.soinside.com 2019 - 2024. All rights reserved.