我们使用Guice Persist在项目中注入EntityManager。
例如。
public class MyDao{
@Inject
EntityManager em;
public void someMethod(){
//uses em instance
}
}
但我们不清楚如何使用EntityManager
的注入实例。
EntityManagerFactory对其进行实例化。createEntityManager()
所以我认为它是应用程序管理的实体管理器。但在官方维基上,他们写的是seesion per transaction策略,这表明EntityManager是(伪)事务范围的
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作用域
我对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)
尽管Piotr完美地回答了这个问题,但我想补充一些关于如何使用guice persist的实用建议。
我一直有一些问题,很难调试。在我的应用程序中,某些线程会显示过时的数据,有时EntityManager
实例会留下旧的死数据库连接。根本原因在于我使用@Transactional
注释的方式(我只将它们用于执行更新/插入/删除的方法,而不是只读方法)。只要在注入的提供程序上调用
get()
,guice persist就会将EntityManager
实例存储在ThreadLocal
中
因此,只要您坚持以下简单规则,guice persist的用法就很简单:
始终插入提供程序
希望这有帮助!
在代码里事务提交后方法结束,此时数据库是否已经执行了事务?因为事务提交返回了成功说明数据库已经处理了这个事务提交,但是此时数据库实际是否已经有执行完成这个事务?还是代码里事务提交完成后数据库实际并没有执行完成,只是先返回了成功的信息?现在碰到一个情况是方法提交结束后另外一个程序立刻调用存储过程查询数据会出现查不到的情况。
通常,默认范围是请求范围。我曾尝试删除范围注释,并希望bean具有请求bean作用域行为(通过在前一页返回提交的值,我记得我过去曾尝试过,效果很好),但我没有得到与之相关的表达式语言。那么默认范围是什么,为什么不是相同的行为?!
问题内容: 在PHP中,您可以… 也就是说,有一个函数可让您通过传递上下限来获得一定范围的数字或字符。 为此,JavaScript是否内置任何内置功能?如果没有,我将如何实施? 问题答案: 它适用于字符和数字,通过可选步骤前进或后退。 jsFiddle。 如果您想扩展本机类型,则将其分配给。
我正在尝试使用Docker的uWSGI为Django应用程序提供服务。我正在使用supervisord在Dockerfile的末尾为我启动流程。当我运行图像时,它说uWSGI进程启动并成功,但我无法在我认为会显示它的URL处查看应用程序。也许我没有正确设置/配置东西? 我现在没有启动nginx,因为我目前正在通过Amazon S3提供静态文件,并且希望首先专注于启动和运行wsgi。 通过执行,我成
问题内容: 我们正在一个小型Web(将在Tomcat上运行)上工作,并使用JPA(Eclipselink)来完成数据层。我前段时间做过类似的事情。但是我总是不确定何时需要开始和结束交易或进行刷新。目前我使用事务(如果我添加(持久)并删除对象)。如果我在已经存在的对象上调用设置器,则不使用事务。 什么时候使用事务或如何正确实现应用程序管理的JPA,是否有指南/教程或简短答案。 问题答案: 我认为可以
问题内容: 我是Spring的新手,我想知道是否可以在同一应用程序中使用多个事务管理器? 我有两个数据访问层-一个用于两个数据库。我想知道,你如何在一个层使用一个事务管理器,而在另一层使用另一个事务管理器。我不需要在两个数据库之间都执行事务。但是我确实需要分别在每个数据库上执行事务。我创建了一个图像来帮助概述我的问题: 这是我的应用程序上下文配置: 这是使用此配置的示例: 因此,对于帐户存储库,我