关于多线程和EntityManager的问题

时间:2011-08-30 17:30:50

标签: jsf-2 glassfish jpa-2.0 glassfish-3 cdi

我一直在使用JPA 2.0实现EclipseLink 2.2.0开发我的web应用程序。我终于开始运行多线程代码了,我得到了这个例外:

java.lang.IllegalStateException: Attempting to execute an operation on a closed EntityManager.

在我的应用程序中具有所有javax.persistence调用的对象被定义为应用程序作用域,如下所示:

@Model
@ApplicationScoped
public class LocationControl implements Serializable {

    @PersistenceContext private EntityManager   em;
    @Resource           private UserTransaction utx;

    // etc

当然,想要访问数据库的所有托管bean(通常是RequestScoped或ConversationScoped)都是这样的:

@Inject private LocationControl lc;

所以我的问题是:我是否通过使用@ApplicationScoped DAO得到了这个例外?我曾经认为这样会更有效率,因为如果没有范围,容器就不必在每个请求上不断地重新创建这个对象,并且DAO没有自己的状态。但是,如果EntityManager和UserTransaction对象必须是每个用户的单独实例,那么这将是一个问题。

或者,我可以在DAO方法上使用syncrhonized,但我认为这会导致容器中的线程锁定(GlassFish)。

任何建议表示赞赏。

1 个答案:

答案 0 :(得分:1)

@Model注释最初是为注释请求范围的bean而创建的,以下是它的定义方式:

@Named

@RequestScoped

@Stereotype

@Target({TYPE, METHOD, FIELD})

@Retention(RUNTIME)

public @interface Model {}

您当然可以使用另一个注释覆盖'@RequestScoped'但是'@ApplicationScoped'这不是一个好选择,因为应用程序中的每个人都会修改相同注入的EntityManager的状态。我认为最好在大多数情况下保留@RequestScoped,有时,例如对于登录/注销数据bean'@SessionScoped'可能是一个选项,但我看不到'@ApplicationScoped'dao的场景。

如果您根本不想使用@Model并且使用完整的Java EE容器,那么无状态EJB(如BalusC所说)对Dao来说也是一个很好的选择。