Spring JPA:具有@Transactional和@PersistenceContext的应用程序管理的持久性上下文 [英] Spring JPA : Application managed persistence context with @Transactional and @PersistenceContext

查看:147
本文介绍了Spring JPA:具有@Transactional和@PersistenceContext的应用程序管理的持久性上下文的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当前,我正在尝试通过手动创建实体管理器并存储它们来启用跨JSE应用程序中多个请求调用(例如扩展持久性上下文之类的事务)的事务,以尝试由应用程序管理的持久性上下文.

Currently im trying out the application managed persistence context, by creating the entity manager manually and store them to enable transaction that spans multiple request calls (perhaps something like extended persistence context) in JSE application.

但是,我想知道是否可以通过使用spring的@PersistenceContext注入并使用@Transactional批注标记方法来使用手动启动的事务来避免在整个服务和DAO方法中将entityManager对象作为附加参数发送实体经理.

But, im wondering whether i can avoid sending the entityManager object throughout the service and DAO methods as an additional parameter by making use of the spring's @PersistenceContext injection and mark the methods with @Transactional annotation to use the transaction started manually with that entity manager.

我认为我可以通过使用ThreadLocal对此功能进行管理,但是我很乐意将其附加到spring框架上.

I think i can somehow manage this by using a ThreadLocal for this feature, but i'll be happier to be able to attach this to the spring framework.

这是我心目中的一个例子:

This is an example of What i have in mind :

UI操作方法:

在这里我们可以看到事务是由ui逻辑启动的,因为在后端没有用于将这些调用分组到业务逻辑的facade/command方法:

Here we can see the transaction is started by the ui logic, since there iss no facade / command method in the backend to group these callings to the business logic :

Long transactionid = tool.beginTransaction();

// calling business methods
tool.callBusinessLogic("purchase", "receiveGoods", 
                        paramObject1, transactionid);

tool.callBusinessLogic("inventory", "updateInventory", 
                        paramObject2, transactionid);

tool.commitTransaction(transactionid);


工具内:


Inside the tool :

public Long beginTransaction() {
  // create the entity --> for the @PersistentContext
  Entitymanager entityManager = createEntityManagerFromFactory();
  long id = System.currentTimeMillis();
  entityManagerMap.put(id, entitymanager);

  // start the transaction --> for the @Transactional ?
  entityManager.getTransaction().begin();

  return id;
}

public void commitTransaction(Long transactionId) {
  EntityManager entityManager = entityManagerMap.get(transactionId);

  entityManager.getTransaction().commit();
}

public Object callBusinessLogic(String module, String function, 
                        Object paramObject, Long transactionid) {
    EntityManager em = entityManagerMap.get(transactionId);

    // =================================
    //        HOW TO DO THIS????
    // =================================
    putEntityManagerIntoCurrentPersistenceContext(em);

    return executeBusinessLogic(module, function, paramObject, transactionid);
}


以及服务方法示例:


And the example for the service method :

public class Inventory {
  // How can i get the entityManager that's been created by the tool for this thread ?
  @PersistenceContext
  private EntityManager entityManager;

  // How can i use the transaction with that transactionId ?
  @Transactional
  public void receiveGoods(Param param) {
    // ........
  }
}


反正有实现这一目标的方法吗?


Is there anyway to achieve this ?

谢谢!

推荐答案

Spring对@PersistenceContext批注的处理确实几乎完全符合您的要求,但有一个很大的不同:您总是得到一个事务作用域的EntityManager和Spring总是为同一线程注入相同的实例,因此您可以进行传播,而不必担心线程安全性.但是您永远不会以这种方式获得扩展的上下文!
相信我,Spring 3和扩展的持久性上下文不能一起很好地发挥作用,也许这在Spring 3.1中会有所改变,但恐怕并不是他们关注的重点.如果要使用扩展的持久性上下文,请让Spring注入EntityManagerFactory(通过@PersistenceUnit批注),然后自行创建EntityManager.为了进行传播,您必须将实例作为参数传递或自己将其存储在ThreadLocal中.

Spring's handling of the @PersistenceContext annotation does almost exactly what you're after, with one big difference: you always get a transaction scoped EntityManager and Spring injects always the same instance for the same thread, so you have kind of propagation and don't have to worry about thread-safety. But you'll never get an extended context this way!
Believe me, Spring 3 and extended persistence context don't play well together, maybe this will change in Spring 3.1 but I'm afraid that's not in their focus. If you want to use an extended persistence context let Spring inject the EntityManagerFactory (via @PersistenceUnit annotation) and then create the EntityManager on your own. For propagation you'll have to either pass the instance as a parameter or store it in a ThreadLocal yourself.

这篇关于Spring JPA:具有@Transactional和@PersistenceContext的应用程序管理的持久性上下文的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆