Java GWT和JPA并发,@PersistenceContext,NullPointerException

Java GWT和JPA并发,@PersistenceContext,NullPointerException,java,jpa,gwt,eclipselink,Java,Jpa,Gwt,Eclipselink,我有一个纯JAVA项目,我用maven在eclipse中开发。它有一个持久性功能,使用JPA和EclipseLink将数据保存到ApacheDerby中。该项目在单元测试和独立java应用程序中运行良好,在这些应用程序中,我直接从代码实例化EntityManagerFactory: 公共类JPAUtil { 私有静态EntityManagerFactory=Persistence.createEntityManagerFactory(“单元名称”); 私有静态映射ems=newhashmap()

我有一个纯JAVA项目,我用maven在eclipse中开发。它有一个持久性功能,使用JPA和EclipseLink将数据保存到ApacheDerby中。该项目在单元测试和独立java应用程序中运行良好,在这些应用程序中,我直接从代码实例化EntityManagerFactory:

公共类JPAUtil
{
私有静态EntityManagerFactory=Persistence.createEntityManagerFactory(“单元名称”);
私有静态映射ems=newhashmap();
私有JPAUtil(){}
/**
*获取实体管理器
*/
公共静态实体管理器em(长id)
{       
EntityManager结果=空;
如果(ems.containsKey(id))
{
结果=ems.get(id);
如果(!result.isOpen())
{
结果=createEntityManager();
ems.put(id、结果);
}
}
其他的
{
结果=createEntityManager();
ems.put(id、结果);
}
返回结果;
}
私有静态EntityManager createEntityManager()
{
实体管理器结果=
//createEntityManager(SynchronizationType.SYNCHRONIZED);
createEntityManager();
返回结果;
}
}
现在,当我将它添加到GWT项目中时,我遇到了一些非常难以调试/解决的问题

问题1:

如果我使用上面的JPAUtil类来实例化EntityManager,以便在每个RPC请求上使用,它就会工作。但是,如果GWT客户端开始向服务器端发出多个请求,而服务器端又试图从JPA层提取数据,则在读取时会发生多个神秘的并发异常(有无延迟加载-这似乎没有什么区别)

当我没有使用上述类,而是尝试使用以下行将EntityManager“注入”到GWT ServiceImpls(servlet)中时,试图访问数据层会导致NullPointerException崩溃:

@PersistenceContext(unitName=“unitName”)
瞬态保护实体管理器em;
我显然在想,这将是从GWT访问持久层的更合适的方法。但是,当访问EntityManager时,我会遇到NullPointerException,因为GWT的开发Jetty服务器无法自行注入EntityManager。我处理这类问题的能力似乎有限,而我的谷歌浏览器似乎也无能为力。因此,要提出一个具体问题:

如何最好地解决在后端使用JPA创建快速、稳定的GWT应用程序的问题

提前谢谢大家,,
el.nicko

您需要同步对
HashMap
的访问,因为许多RPC请求可以由多个线程并行处理。建议您将
HashMap
替换为
ConcurrentHashMap
或将synchronize放在
em
方法上


@Inject
可能无法工作,因为GWT servlet不知道CDI。

谢谢您的回答!不知道我怎么会错过。您提出的更改减少了向用户抛出的并发异常。它似乎没有完全解决这个问题。然而,更深入的挖掘使这一天变得更加美好:它解决了同时向数据库写入数据的问题,而不是读取数据的问题,这是最令人沮丧的部分,因为它根本不应该发生。并发读取问题隐藏在DAO层的深处,其中一个DAO有EntityManager的本地副本。解决了这个问题。愚蠢的人为错误:-)非常感谢,标记为已解决。关于一个稍微相关的主题-启用EntityManager注入而不是由应用程序控制它的最合适的方法是什么?春天如果它能跨所有应用程序容器工作,那将是最好的。很高兴听到这个消息。我在gwt plus spring方面的经验不足,尽管这可能是可行的。建议你把这当作一个新问题来问。