当前位置: 首页 > 知识库问答 >
问题:

Guice Persist是否提供事务范围的或应用程序管理的EntityManager?

商泽宇
2023-03-14

我们使用Guice Persist在项目中注入EntityManager。

例如。

public class MyDao{
   @Inject
   EntityManager em;

   public void someMethod(){
       //uses em instance
   }
}

但我们不清楚如何使用EntityManager的注入实例。

  1. 这是什么类型的实体管理器?(参见例如:实体管理器的类型)在hood Guice下,Persist通过EntityManagerFactory对其进行实例化。createEntityManager()所以我认为它是应用程序管理的实体管理器。但在官方维基上,他们写的是seesion per transaction策略,这表明EntityManager是(伪)事务范围的

共有3个答案

戚阳
2023-03-14

1.这取决于您的模块配置。有一些基本绑定:

JpaPeristanceService

public class JpaPersistanceService implements Provider<EntityManager> {

  private EntityManagerFactory factory;

  public JpaPersistanceService(EntityManagerFactory factory) {
    this.factory = factory;
  }

  @Override
  public EntityManager get() {
    return factory.createEntityManager();
  }
}

模块绑定

EntityManagerFactory factory = Persistence.createEntityManagerFactory(getEnvironment(stage));
bind(EntityManager.class).annotatedWith(Names.named("request")).toProvider(new JpaPersistanceService(factory)).in(RequestScoped.class);
bind(EntityManager.class).annotatedWith(Names.named("session")).toProvider(new JpaPersistanceService(factory)).in(SessionScoped.class);
bind(EntityManager.class).annotatedWith(Names.named("app")).toProvider(new JpaPersistanceService(factory)).asEagerSingleton;

用法

@Inject @Named("request")
private EntityManager em; //inject a new EntityManager class every request

@Inject @Named("session")
private Provider<EntityManager> emProvider; //inject a new EntityManager class each session
//This is little bit tricky, cuz EntityManager is stored in session. In Stage.PRODUCTION are all injection created eagerly and there is no session at injection time. Session binding should be done in lazy way - inject provider and call emProvider.get() when em is needed;

@Inject @Named("application")
private EntityManager em; //inject singleton

2.是的,您应该或者将使用JpaPersistModule[javadoc]

3.这是关于持久化中的JPA配置。xml和EntityManager作用域

冯曾笑
2023-03-14

我对Guice persist的源代码进行了一些研究,并在Guice persist wiki页面下通读了评论,以下是我需要的答案:

1.如果通过@Inject EntityManager注入EntityManager,EntityManager的生命周期管理就有点崩溃了。正如Wiki上的一条评论所述:

我确认直接向EntityManager而不是提供者注入可能是危险的。如果您不在UnitOfWork或带有@Transaction注释的方法中,那么在线程中第一次注入EntityManager将创建一个新的EntityManager,永远不要销毁它,并始终为此线程使用此特定的EntityManager(EM存储在线程本地)。这可能会导致可怕的问题,比如注入死亡的entityManager(连接关闭等),因此我建议您始终注入提供者,或者至少直接在打开的UnitOfWork中注入entityManager。

所以我问题中的例子并不是最正确的用法。它创建EntityManager的单例实例(每个线程),并将在任何地方注入该实例:-(。

然而,如果我注入了Provider并在@Transactional方法中使用它,那么EntityManager的实例将是每个事务。因此,这个问题的答案是:如果注入和使用正确,实体管理器是事务范围的。

2.如果注入和使用正确,那么我不需要手动关闭实体管理器(guice persist将为我处理)。如果使用不当,手动关闭将是一个非常糟糕的主意(当I@Inject EntityManager时,EntityManager的已关闭实例将被注入每个地方)

3.如果注入并正确使用,则一级缓存的范围是单事务。如果使用不当,一级缓存的作用域就是应用程序的生命周期(EntityManager是singleton)

祁鸿晖
2023-03-14

尽管Piotr完美地回答了这个问题,但我想补充一些关于如何使用guice persist的实用建议。

我一直有一些问题,很难调试。在我的应用程序中,某些线程会显示过时的数据,有时EntityManager实例会留下旧的死数据库连接。根本原因在于我使用@Transactional注释的方式(我只将它们用于执行更新/插入/删除的方法,而不是只读方法)。只要在注入的提供程序上调用get(),guice persist就会将EntityManager实例存储在ThreadLocal

因此,只要您坚持以下简单规则,guice persist的用法就很简单:

  1. 始终插入提供程序

希望这有帮助!

 类似资料:
  • 通常,默认范围是请求范围。我曾尝试删除范围注释,并希望bean具有请求bean作用域行为(通过在前一页返回提交的值,我记得我过去曾尝试过,效果很好),但我没有得到与之相关的表达式语言。那么默认范围是什么,为什么不是相同的行为?!

  • 问题内容: 在PHP中,您可以… 也就是说,有一个函数可让您通过传递上下限来获得一定范围的数字或字符。 为此,JavaScript是否内置任何内置功能?如果没有,我将如何实施? 问题答案: 它适用于字符和数字,通过可选步骤前进或后退。 jsFiddle。 如果您想扩展本机类型,则将其分配给。

  • 我正在尝试使用Docker的uWSGI为Django应用程序提供服务。我正在使用supervisord在Dockerfile的末尾为我启动流程。当我运行图像时,它说uWSGI进程启动并成功,但我无法在我认为会显示它的URL处查看应用程序。也许我没有正确设置/配置东西? 我现在没有启动nginx,因为我目前正在通过Amazon S3提供静态文件,并且希望首先专注于启动和运行wsgi。 通过执行,我成

  • 问题内容: 我们正在一个小型Web(将在Tomcat上运行)上工作,并使用JPA(Eclipselink)来完成数据层。我前段时间做过类似的事情。但是我总是不确定何时需要开始和结束交易或进行刷新。目前我使用事务(如果我添加(持久)并删除对象)。如果我在已经存在的对象上调用设置器,则不使用事务。 什么时候使用事务或如何正确实现应用程序管理的JPA,是否有指南/教程或简短答案。 问题答案: 我认为可以

  • 问题内容: 我是Spring的新手,我想知道是否可以在同一应用程序中使用多个事务管理器? 我有两个数据访问层-一个用于两个数据库。我想知道,你如何在一个层使用一个事务管理器,而在另一层使用另一个事务管理器。我不需要在两个数据库之间都执行事务。但是我确实需要分别在每个数据库上执行事务。我创建了一个图像来帮助概述我的问题: 这是我的应用程序上下文配置: 这是使用此配置的示例: 因此,对于帐户存储库,我

  • 问题 是否可以创建一个动态ValueRangeProvider,其值范围取决于规划变量的当前值?或者有什么其他的方法可以达到这种想要的效果? 轮班需要分配员工,以便尽可能多地覆盖轮班的持续时间 员工只能在每个轮班和每个员工唯一的特定时间内开始 员工和他们的开始时间都需要作为严格的硬约束进行优化(员工不能被安排到没有可用时间的班次,而且开始时间也不能超出该员工在该班次的可用时间) 员工工作的持续时间