Spring JPA : Application managed persistence context with @Transactional and @PersistenceContext

标签 spring jpa jpa-2.0

目前我正在尝试应用程序管理的持久性上下文,方法是手动创建实体管理器并将它们存储以在 JSE 应用程序中启用跨越多个请求调用(可能类似于扩展持久性上下文)的事务。

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

我想我可以通过对这个特性使用 ThreadLocal 来以某种方式管理这个,但我会更高兴能够将它附加到 spring 框架中。

这是我想到的一个例子:

UI 操作方法:

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

Long transactionid = tool.beginTransaction();

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

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

tool.commitTransaction(transactionid);

工具内部:
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);
}

以及服务方法的示例:
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) {
    // ........
  }
}

有没有办法做到这一点?

谢谢 !

最佳答案

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

关于 Spring JPA : Application managed persistence context with @Transactional and @PersistenceContext,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5101407/

相关文章:

java - 使用 CriteriaBuilder (JPA) 进行子选择以检索语句内的右侧

java - JPA 注释的两个不同位置

java - 通过实体图加载元素集合时,SqlNode 的文本未引用预期的列数错误

java - Spring MVC 路径模式匹配不处理破折号

java - 如何在 Spring Boot 中设置 useBodyEncodingForURI ="true"

java - 如何离线模式运行spring项目?

java - manytomany 检索条件

java - 如何告诉 EclipseLink 在 SQL 中使用完整的表名称作为别名

jpa - 如何从 EclipseLink 捕获约束违规异常?

java - netbeans,无法部署Web项目