关于多线程和EntityManager的问题
我一直在使用 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 方法上使用同步,但我认为这会导致容器(GlassFish)中的线程锁定。
任何建议表示赞赏。
I have been developing my web-app using JPA 2.0 implementation EclipseLink 2.2.0. I finally got around to running multi-threaded code and I got this exception:
java.lang.IllegalStateException: Attempting to execute an operation on a closed EntityManager.
The objects that have all the javax.persistence calls in my application are defined as application scoped, like this:
@Model
@ApplicationScoped
public class LocationControl implements Serializable {
@PersistenceContext private EntityManager em;
@Resource private UserTransaction utx;
// etc
And of course all the managed beans (usually RequestScoped or ConversationScoped) that want to access the data base do so like this:
@Inject private LocationControl lc;
So my question is this: Did I get that Exception through the use of @ApplicationScoped DAO? I had thought that it would be more efficient that way, since the container would not have to be continually re-creating this object on every request if it did not have a scope, and the DAO has no state of its own. However if the EntityManager and UserTransaction object have to be separate instances for each user, then that would be a problem.
Alternatively, I could use syncrhonized on the DAO methods, but I think that would cause thread lockups in the container (GlassFish).
Any advice appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
@Model 注释最初是为了注释请求范围的 beans 而创建的,它的定义如下:
您当然可以用另一个注释覆盖“@RequestScoped”,但是“@ApplicationScoped”这不是一个好的选择,因为应用程序中的每个人都会修改相同的注入EntityManager。我认为在大多数情况下最好将其保留为@RequestScoped,有时,例如对于登录/注销数据bean“@SessionScoped”可能是一个选项,但我看不到“@ApplicationScoped”dao 的场景。
如果您根本不想使用 @Model 并且使用完整的 Java EE 容器,那么无状态 EJB(正如 BalusC 所说)对于 Dao 来说也是一个不错的选择。
@Model annotation was originally created to annotate request scoped beans, here is how it's defined:
You can of course override '@RequestScoped' with another annotation but '@ApplicationScoped' it's not a good choice as everyone in the application would modify the state of the same injected EntityManager. I think it would be best to leave it @RequestScoped in most cases, sometimes, for example for a login/logout data bean '@SessionScoped' could be an option but I cannot see a scenario for '@ApplicationScoped' dao.
If you don't want to use @Model at all and you use full Java EE container, then the stateless EJB ,as BalusC said, would be a great option for Dao too.