我希望从已成功将JPA与传统类型产品集成的人那里得到一些反馈。最近,我们的软件团队一直在考虑将JPA功能添加到我们的J2EE软件堆栈中。 JPA的强大功能和灵活性给我们留下了深刻的印象,但是很难将它整合到一起,干净利落地#34;与当前的架构。我们在网上找到的大多数JPA示例都太简单,无法应用于我们当前的架构。
我们当前的架构是深层嵌套的。它通常是面向用户的#7;托管"深度为7-8层。 bean到数据库层(有时候更深)。我们的问题是@PersistenceContext只能在ManagedBeans上使用。我们不想制作所有这些数据访问器类MangedBeans,因为这将导致数十个(如果不是数百个)bean。更不用说你必须为它们之间的7-8层中的每一层注入,使它们也成为所有豆类。这简直失控了。
我们尝试过的一个想法,可能是个坏主意,就是拥有一个可以跟踪注入的EntityManager的单例,然后在任何层访问它。但是,在重新部署应用程序时我们已经看到了这个问题(我假设由于过时的类)。
从过去做过类似事情的人那里得到反馈会很棒。在这个发展阶段重新架构是不可能的。有没有一个很好的方法来做到这一点,或者我们是否试图在一个圆孔中安装一个方形钉?
提前致谢,
Weblogic 12.1.2
JPA2.0 - EclipesLink
答案 0 :(得分:0)
我做了一些类似于你提出的'单例'方法(尽管没有使用依赖注入或容器管理的单例)。我做的大致是:
public static EntityManager getEntityManager(HttpServletRequest request) {
//first, check for a cached instance
EntityManager cachedEm = (EntityManager)request.getAttribute(Constants.ENTITY_MANAGER_REQUEST_KEY);
if (cachedEm != null) {
if (! cachedEm.isOpen()) {
//somebody has closed the cached EntityManager; discard it and get a new one
request.removeAttribute(Constants.ENTITY_MANAGER_REQUEST_KEY);
return getEntityManager(request);
}
return cachedEm;
}
//no cached instance, get a fresh one from the factory and cache it for this request
cachedEm = factory.createEntityManager();
request.setAttribute(Constants.ENTITY_MANAGER_REQUEST_KEY, cachedEm);
return cachedEm;
}
所以我有一个静态可访问的实用程序函数,可用于获取当前请求的EntityManager
键。这确保了在正常情况下,与给定HTTP请求相关的所有处理都将使用单个EntityManager
(还有一些用于创建ad-hoc /独立EntityManager
实例的其他方法,适用于少数几个这样做有用和适当的情况)。包含此实用程序功能的类不是容器管理的;它只是一个香草静态实用类。
我还连接了它,以便监视进程的Spring控制器在呈现/写入响应后自动关闭请求EntityManager
,这意味着代码中只有一个点我需要担心在close()
上调用EntityManager
。所以它非常接近容器管理的持久性,没有定制的容器管理。
无法真正评论这种方法与热(重新)部署的效果如何(我很少在实践中进行热部署,因为我注意到它们往往会在PermGen
空间内烧掉,即使其他所有内容也是如此虽然我没有看到它的任何具体问题,但它的工作原理应该如此。我也没有看到任何原因。
如果您的容器/网络框架是试图不惜一切代价隐藏HttpServletRequest
的人之一,那么这种方法可能有点笨重(和/或您必须将其修改为使用你的框架给你的任何请求代理。如果你使用模拟对象进行大量测试,显然静态实用程序类会让它变得更加困难。但实际上,上述代码在几个不同的应用程序中非常有用。