我一直在使用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)。
任何建议表示赞赏。
答案 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来说也是一个很好的选择。