【问题标题】:Spring transactions, EntityManager lifecycleSpring事务,EntityManager生命周期
【发布时间】:2015-04-21 15:02:25
【问题描述】:

我正在开发一个带有 spring 框架的项目。 我有以下架构:所有数据库代码都在 dao 类中,所有应用程序逻辑都在服务类中,http 请求使用 spring mvc rest 控制器处理。

@Repository
public class UserDao {

    @PersistenceContext
    private EntityManager em;

    public void editUser(User user) {
        ...
    }
}

@Service
public class UserService {

    @Autowired
    private UserDao userDao;

    @Transactional
    public void editUser(User user) {
        ...
    }
}

@RestController
@RequestMapping(value = "/UserCtrl", produces = "application/json;charset=UTF-8")
public class UserCtrl {

    private static final Logger logger = LogManager.getLogger(AppConfig.LOGGER_NAME);

    @Autowired
    private ApplicationContext appContext;

    @RequestMapping(value = "/editUser")
    public ActionResult editUser(@ModelAttribute User user) {
        ActionResult rslt = new ActionResult();

        try {
            UserService userService = appContext.getBean(UserService.class);
            userService.editUser(user);

            rslt.setSuccess(true);
        } catch (Exception ex) {
            logger.error("editUser", ex);
            rslt.setSuccess(false);
        }

        return rslt;
    }
}

此代码可以正常工作。 我无法理解的一件事是当 EntityManager 仅在 UserDao 类中注入时,UserService bean 的 aop 代理如何启动事务。有人可以解释一下这是如何工作的以及 Spring 框架如何管理 EntityManager 生命周期吗?

任何帮助表示赞赏。

【问题讨论】:

    标签: java spring transactions entitymanager


    【解决方案1】:

    TransactionManager 负责管理事务边界 在 Spring 框架中。 当您使用 @Transactional 注释业务方法时,您正在使用方面来检测方法。 在执行该方法之前,此方面与 TransactionManager 交互,后者决定是否需要创建新的 Transaction 或使用预先存在的 Transaction。在创建新事务的情况下,从 EntityManagerFactory 创建一个新的实体管理器,并与事务一起与当前线程相关联。

    EntityManager 负责与数据库进行迭代。当您使用@PersistenceContext 注入它时,Spring 会向 EntityManager 注入一个代理。 每当在 EntityManager 代理中执行操作时,它都会查找与线程关联的 EntityManager。

    【讨论】:

    【解决方案2】:

    根据您提供的代码的 sn-p,您正在使用 Spring 和 JPA 的一些实现,您正在为您的 Web 应用程序使用 J2EE 容器,并且基于我的猜测,我认为 this 是关于事情如何工作的好文章。

    基本概念:

    1. EntityManager - 管理实体持久状态(或生命周期)的类。
    2. 持久性单元 - 是实体类的命名配置。
    3. 持久性上下文 - 是一组托管的实体实例。实体类是持久性单元配置的一部分。
    4. 托管实体 - 如果实体实例是持久性上下文的一部分并且实体管理器可以对其进行操作,则它是托管的。

    根据本文,您通过使用 @PersistenceContext 来使用容器托管实体管理器

    当应用程序的容器(Java EE 容器或任何其他自定义容器,如 Spring)管理实体管理器的生命周期时,实体管理器被称为容器管理。获取 Container Managed EntityManager 的最常见方法是在 EntityManager 属性上使用@PersistenceContext 注解。

    而且注入是这样的:

    只要解析了@PersistenceContext 创建的引用,就会返回事务范围实体管理器。

    每次在实体管理器上调用操作时,容器代理(容器在实例化实体管理器时围绕实体管理器创建代理)检查 JTA 事务上的任何现有持久性上下文。如果找到,实体管理器将使用此持久性上下文。如果没有找到,那么它将创建一个新的持久性上下文并将其与事务相关联。

    所以实体管理器的生命周期是由你的容器管理的,

    我们使用 EntityManager 的一个实例,EntityManager 的唯一作用是确定 Persistence Context 的生命周期。它在规定持久性上下文应该如何表现方面没有任何作用。重申一下,持久性上下文是一组托管的实体实例。每当事务开始时,持久性上下文实例就会与之关联。当一个事务结束(例如提交)时,持久性上下文被刷新并与事务解除关联。

    简而言之,通过您提供的 EntityManagerFactory 实例化您的 EntityManager 并管理它的生命周期,但为您注入 EntityManager 的代理。 TransactionManager 负责根据您提供的注释创建、提交和...事务,每当它开始事务时,与它关联的 PersistancecContext 以及当事务结束时,它会提交 PersistenceContext 的状态。 EntityManager 与 PersistenceContext 一起使用,如果没有提供,EntityManager 会创建一个。 EntityManager 是线程安全的,只要它不保存任何状态并且状态(PersistenceContext)附加到当前事务。

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 2014-12-04
      • 2013-07-07
      • 2023-01-22
      • 1970-01-01
      • 2011-08-05
      • 2011-07-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多