是否可以将注入的EntityManagers传递给EJB bean的帮助程序类并使用它?

Enn*_*oji 6 java jpa thread-safety java-ee ejb-3.0

我们有一些JavaEE5无状态EJB bean,它将注入的EntityManager传递给它的帮助器.

这样安全吗?到目前为止它一直运行良好,但我发现了一些Oracle文档,声明它的EntityManager实现是线程安全的.现在我想知道我们到目前为止没有问题的原因是因为我们使用的实现恰好是线程安全的(我们使用Oracle).

@Stateless
class SomeBean {
    @PersistenceContext
    private EntityManager em;

    private SomeHelper helper;

    @PostConstruct
    public void init(){
        helper = new SomeHelper(em);
    }

    @Override
    public void business(){
        helper.doSomethingWithEm();
    }

}
Run Code Online (Sandbox Code Playgroud)

实际上它是有道理的..如果EntityManager是线程不安全的,那么容器就必须这样做

inercept business()
this.em = newEntityManager();
business();
Run Code Online (Sandbox Code Playgroud)

它不会传播到其辅助类.

如果是这样,在这种情况下最好的做法是什么?传递EntityManagerFactory而不是EntityManager?

编辑:这个问题非常有趣,所以如果你对这个问题感兴趣,你可能也想看一下这个问题:

编辑:更多信息. ejb3.0规范

4.7.11非重入实例 容器必须确保任何时候只有一个线程可以执行实例.如果客户端请求在实例执行另一个请求时到达实例,则容器可能会将javax.ejb.ConcurrentAccessException抛出到第二个客户端[24].如果使用EJB 2.1客户端视图,如果客户端是远程客户端,容器可能会将java.rmi.RemoteException抛出到第二个请求,如果客户端是本地客户端,则容器可能抛出javax.ejb.EJBException.[25] 请注意,会话对象仅支持单个客户端.因此,如果两个客户端尝试调用同一会话对象,则会出现应用程序错误.此规则的一个含义是应用程序无法对会话Bean实例进行环回调用.

和,

4.3.2依赖注入 会话bean可以使用依赖注入机制来获取对其环境中的资源或其他对象的引用(请参阅第16章"Enterprise Bean Environment").如果会话bean使用依赖注入,则容器会在创建bean实例之后,以及在bean实例上调用任何业务方法之前注入这些引用.如果声明了对SessionContext的依赖,或者bean类实现了可选的SessionBean接口(参见第4.3.5节),则此时也会注入SessionContext.如果依赖项注入失败,则丢弃bean实例.在EJB 3.0 API下,bean类可以通过依赖注入获取SessionContext接口,而无需实现SessionBean接口.在这种情况下,Resource annotation(或resource-env-ref部署描述符元素)用于表示bean对SessionContext的依赖性.请参见第16章"Enterprise Bean Environment".

ewe*_*nli 2

我使用了类似的模式,但创建了助手@PostConstruct,并将注入的实体管理器作为参数传递到构造函数中。每个 EJB 实例都有自己的帮助程序,这样线程安全就得到了保证。

\n\n

我还有一个变体,即实体管理器未注入(因为 EJB 没有完全使用它),因此助手必须使用InitialContext. 在这种情况下,持久性上下文仍然必须通过以下方式“导入”到父 EJB 中@PersistenceContext

\n\n
@Stateless \n@PersistenceContext(name="OrderEM") \npublic class MySessionBean implements MyInterface { \n  @Resource SessionContext ctx; \n  public void doSomething() { \n     EntityManager em = (EntityManager)ctx.lookup("OrderEM"); \n     ... \n  } \n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

但实际上注入它(即使 EJB 不使用它)比查找它更容易,尤其是对于可测试性而言。

\n\n

但回到您的主要问题,我认为注入或查找的实体管理器是一个包装器,它转发到绑定到事务的底层活动实体管理器。

\n\n

希望能帮助到你。

\n\n

编辑

\n\n

规范中的 \xc2\xa7 3.3 和 \xc2\xa7 5.6 部分涵盖了一些主题。

\n