2011-08-30 84 views
0

我一直在使用JPA 2.0实现EclipseLink 2.2.0开发我的web应用程序。我终于可以运行多线程代码,我得到这个异常:关于多线程和EntityManager的问题

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)。

任何意见赞赏。

+0

我没有做CDI,但'LocationControl'通常应该是一个'@ Stateless' EJB,并且要被'@ EJB'注入。我不知道'@ Model'代表什么,但是这对商业服务类来说是错误的。 – BalusC

回答

1

@Model注释最初创建注释请求范围豆,这里是它是如何定义的:

@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来说也是一个很好的选择。

+0

我认为我们在这里对'@Model'的用法有偏见。实际上它是'@Named'的扩展,我将我的代码转换为使用'@Named'。但真正的问题是,我是否可以使用单个DAO实例来引用具有多个线程的单个EntityManager和UserTransaction。 – AlanObject

+0

即使您使用'@Named'而不是'@Model',仍然使用'@ApplicationScope',您将使您的实体管理器成为全局的,并且我认为它不应该是。 – Kris

+0

好吧,我想我将不得不这样做。感谢您的输入。 – AlanObject