是否可以将注入的EntityManagers传递给EJB bean的帮助程序类并使用它? [英] Is it okay to pass injected EntityManagers to EJB bean's helper classes and use it?

查看:144
本文介绍了是否可以将注入的EntityManagers传递给EJB bean的帮助程序类并使用它?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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

  @Stateless 
class SomeBean {
@PersistenceContext
private EntityManager em;

私人SomeHelper助手;

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

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

}

实际上它是有意义的..如果的EntityManager是线程不安全的,容器必须做

  inercept业务()
this.em = newEntityManager( );
business();

不会传播到其助手类。



如果是这样,在这种情况下最好的做法是什么? ?使代替的EntityManager EntityManagerFactory的



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



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


4.7.11非重入实例
容器必须确保只有一个
线程可以随时以
执行实例。如果一个实例的客户端请求到达
,而实例是
执行另一个请求,
容器可能会将
javax.ejb.ConcurrentAccessException抛出到
第二个客户端[24]。如果使用EJB 2.1
客户端视图,如果客户端是
远程客户端或$,则容器可能
将java.rmi.RemoteException抛出到
第二个请求b $ b 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-env-ref部署
描述符元素)用于表示bean对
SessionContext的依赖性
。见第16章,
的企业bean环境。



解决方案

我使用的类似的模式,但帮助器是在 @PostConstruct 中创建的,并且注入的实体管理器在构造函数中作为参数传递。每个EJB实例都有自己的帮助器,然后保证线程安全。



我还有一个变体是实体管理器没有被注入(因为EJB没有完全使用它),所以帮助者必须用<$查找它C $ C>的InitialContext 。在这种情况下,Persistence上下文仍然必须在父EJB中导入 @PersistenceContext

  @Stateless 
@PersistenceContext(名称= OrderEM)
公共类MySessionBean实现MyInterface的{
@Resource SessionContext CTX;
public void doSomething(){
EntityManager em =(EntityManager)ctx.lookup(OrderEM);
...
}
}

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



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



希望有所帮助。



编辑



规范中的§3.3和§5.6部分涵盖了主题。


We have some JavaEE5 stateless EJB bean that passes the injected EntityManager to its helpers.

Is this safe? It has worked well until now, but I found out some Oracle document that states its implementation of EntityManager is thread-safe. Now I wonder whether the reason we did not have issues until now, was only because the implementation we were using happened to be thread-safe (we use 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();
    }

}

Actually it makes sense.. If EntityManager is thread-unsafe, a container would have to do

inercept business()
this.em = newEntityManager();
business();

which will not propagate to its helper classes.

If so, what is the best practice in this kind of a situation? Passing EntityManagerFactory instead of EntityManager?

EDIT: This question is very interesting so if you are interested in this question, you probably want to check out this one, too:

EDIT: More info. ejb3.0 spec

4.7.11 Non-reentrant Instances The container must ensure that only one thread can be executing an instance at any time. If a client request arrives for an instance while the instance is executing another request, the container may throw the javax.ejb.ConcurrentAccessException to the second client[24]. If the EJB 2.1 client view is used, the container may throw the java.rmi.RemoteException to the second request if the client is a remote client, or the javax.ejb.EJBException if the client is a local client.[25] Note that a session object is intended to support only a single client. Therefore, it would be an application error if two clients attempted to invoke the same session object. One implication of this rule is that an application cannot make loopback calls to a session bean instance.

And,

4.3.2 Dependency Injection A session bean may use dependency injection mechanisms to acquire references to resources or other objects in its environment (see Chapter 16, "Enterprise Bean Environment"). If a session bean makes use of dependency injection, the container injects these references after the bean instance is created, and before any business methods are invoked on the bean instance. If a dependency on the SessionContext is declared, or if the bean class implements the optional SessionBean interface (see Section 4.3.5), the SessionContext is also injected at this time. If dependency injection fails, the bean instance is discarded. Under the EJB 3.0 API, the bean class may acquire the SessionContext interface through dependency injection without having to implement the SessionBean interface. In this case, the Resource annotation (or resource-env-ref deployment descriptor element) is used to denote the bean’s dependency on the SessionContext. See Chapter 16, "Enterprise Bean Environment".

解决方案

I used a similar pattern, but the helper was created in @PostConstruct and the injected entity manager was passed in the constructor as parameter. Each EJB instance had its own helper and thread-safety was guaranteed then.

I also had a variant were the entity manager was not injected (because the EJB wasn't using it altogether), so the helper has to look it up with InitialContext. In this case, the Persistence context must still be "imported" in the parent EJB with @PersistenceContext:

@Stateless 
@PersistenceContext(name="OrderEM") 
public class MySessionBean implements MyInterface { 
  @Resource SessionContext ctx; 
  public void doSomething() { 
     EntityManager em = (EntityManager)ctx.lookup("OrderEM"); 
     ... 
  } 
}

But it's actually easier to inject it (even if the EJB doesn't use it) than to look it up, especially for testability.

But to come back to your main question, I think that the entity manager that is injected or looked up is a wrapper that forwards to the underlying active entity manager that is bound to the transaction.

Hope it helps.

EDIT

The section § 3.3 and § 5.6 in the spec cover a bit the topic.

这篇关于是否可以将注入的EntityManagers传递给EJB bean的帮助程序类并使用它?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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