@ApplicationScoped CDI bean和@PersistenceContext - 这样安全吗? [英] @ApplicationScoped CDI bean and @PersistenceContext - is this safe?

查看:134
本文介绍了@ApplicationScoped CDI bean和@PersistenceContext - 这样安全吗?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用CDI做这样的事情是否安全?

Is it safe to do something like this with CDI?

@Named
@ApplicationScoped
public class DAO {

   @PersistenceContext
   private EntityManager entityManager;

}

我理解 EntityManager 本身不是线程安全的,因此不应在 @ApplicationScoped 等共享全局上下文中使用。但是,由于带有 @PersistenceContext 的注入对象实际上是底层 EntityManager 的线程感知包装器,这个好吗?

I understand that EntityManager itself is not thread-safe, and therefore should not be used in a shared global context like @ApplicationScoped. However, since the injected object with @PersistenceContext is actually a thread-aware wrapper around an underlying EntityManager, does that make this ok?

我已经看过关于这个主题的其他帖子,但是还没能找到这个具体案例的权威答案。例如:

I've seen other posts on the subject but haven't been able to figure out an authoritative answer for this specific case. For example:

Java CDI @PersistenceContext和线程安全

例如,与 @Stateless 一起使用是安全的 - 但我不确定这是因为 @Stateless 的工作方式,还是因为 @PersistenceContext 本身。

It looks like it's safe to use with @Stateless, for instance - but I'm not sure if that's because of the way @Stateless works, or because of something intrinsic to @PersistenceContext itself.

编辑
我混淆的原因是 @PersistenceContext 注入 EntityManager 包装器似乎知道当前线程,以便弄清楚是否已经有正在进行的事务。所以也许我将线程感知与线程安全混淆,它们是两个不同的东西。

EDIT The source of my confusion is that the @PersistenceContext injected EntityManager wrapper seems to be aware of the current thread, in order to figure out whether there's already a transaction in progress. So perhaps I'm confusing thread-awareness with thread-safety and they're two different things.

推荐答案

我很确定在这种情况下,CDI不会为实体管理器创建上下文代理。毕竟,它的范围是什么?您可能想要类似于假设的 @ThreadScoped 或只是 @RequestScoped ,但 @PersistenceContext 不是CDI注释,CDI不会修改它的语义。

I'm pretty sure that in this case CDI does not create a contextual proxy for the entity manager. After all, what scope would it be in? You may want something akin to a hypothetical @ThreadScoped or just @RequestScoped, but @PersistenceContext is not a CDI annotation and CDI does not modify its semantics.

所以这里发生的是Java EE 6平台托管bean注入,类似于在Servlet中注入实体管理器。这两种情况都会为您提供一个不能直接使用的线程安全的实例。

So what's happening here is the Java EE 6 platform "managed bean" injection, which is similar to injecting the entity manager in a Servlet. Both cases give you an instance that is not thread-safe to use directly.


看起来使用@Stateless是安全的,因为实例 - 但我不确定这是因为@Stateless的工作方式,还是因为@PersistenceContext本身固有的东西。

It looks like it's safe to use with @Stateless, for instance - but I'm not sure if that's because of the way @Stateless works, or because of something intrinsic to @PersistenceContext itself.

这是因为 @Stateless 的工作原理。对无状态bean上的方法的每个请求(调用)都由容器路由到唯一的实例。容器保证在同一个bean中没有两个线程处于活动状态。

It's because of the way @Stateless works. Every request (call) to a method on a stateless bean is routed by the container to a unique instance. The container guarantees that no two threads are ever active in the same bean.

使用CDI,您可以通过将实体管理器封装在请求范围的bean中来获得每个请求的类似效果并将其注入应用程序作用域:

With CDI you can get a similar effect per request by encapsulating the entity manager in a request scoped bean and injecting that into the application scoped one:

import javax.enterprise.context.RequestScoped;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;

@RequestScoped
public class EntityManagerProvider {

    @PersistenceContext
    private EntityManager entityManager;

    public EntityManager getEntityManager() {
        return entityManager;
    }

}

将此注入到您所在的bean中以前注入实体经理:

Inject this into the bean where you previously injected the entity manager:

@Named
@ApplicationScoped
public class DAO {

   @Inject
   private EntityManagerProvider entityManagerProvider;

}

这将为每个请求提供一个唯一的实体管理器。您也可以轻松将其转换为生成器方法,因此您不必在注入的提供程序上调用 getEntityManager()

This will give you a unique entity manager per request. You can easily turn this into a producer method as well, so you won't have to call getEntityManager() on the injected provider.

这篇关于@ApplicationScoped CDI bean和@PersistenceContext - 这样安全吗?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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