复合持久单元 - 的Java EE
处理多个实体管理器的方式,即多个持久化单元,在Java EE是使用复合持久性单元(CPU)。这种复合持久性单元可以通过EE网络应用程序中的一个单一点来评估,一个数据层。尽管为了与@PersistenceContext
一起工作,这需要是@Stateless
EE bean。
已经引入了复合持久单元,以便在各种Java应用程序中重用实体类。 CPU是企业架构的一项功能。我选择使用EclipseLink作为展示,因为我从正在运行的生产应用程序中获得了积极的体验。
介绍
在某些情况下,实体包含在一台服务器所需的景观在更多的网络服务的一般数据。以一个通用的'名称地址'实体,'用户密码角色'实体,'文档关键词索引'实体等为例。复合持久性单元的实现方式便于每个实体定义的源在只有一个地方('单点定义')。这些实体定义可以随后包含在每个需要此实体访问的Java Web应用程序中。复合持久性单元的
工作
复合持久性单元的工作由下面的教程所示:EclipseLink composite persistence units
复合持久单元的概念的工作原理是第一限定部件持久单元。每个成员持久性单元可以与不同的数据库关联,但成员持久性单元也可以全部引用相同的实际数据库。我有后者的经验,EclipseLink(版本2.6.4)与一个Postgress数据库结合使用。
Maven需要使所需的模块化方法成为可能。
设置在persistence.xml中
一种复合持久单元构件的定义如下:方案一组相关实体(爪哇@Entity
班),一个接一个,专用的Maven模块中的。在这个Maven模块中定义一个复合持久化单元成员(重要!)。复合单元成员PuPersonData涉及表征人员数据的这组相关实体。定义成员持久化单元PuPersonData为(
<persistence-unit name="PuPersonData" transaction-type="JTA">
...
<jta-data-source>jdbc/PostgresDs</jta-data-source>
...
)。
在第二Maven的模块,定义另一复合持久单元构件,PuWebTraffic(
<persistence-unit name="PuWebTraffic" transaction-type="JTA">
...
<jta-data-source>jdbc/PostgresDs</jta-data-source>
...
)。在此处包括其他存储关于Web事务,登录,会话等的数据的实体(用@Entity
表示的Java类) 不用说明,两个组合持久性单元成员必须与实体不相交,实体中不允许重叠-names。
两个持久性单元成员在他们的XML-定义属性:
<properties>
<property name="eclipselink.composite-unit.member" value="true"/>
...
</properties>
复合持久单元
我们现在在第三Maven的定义模块复合持久单元CPuPersonSessionData同时包含持久性单元成员PuPersonData和PuWebTraffic。
<persistence-unit name="CPuPersonSessionData" transaction-type="JTA">
该复合持久单元CPuPersonSessionData指两个持久性单元构件,PuPersonData和PuWebTraffic,通过包括从所述两个有关的Maven模块的编译的结果的罐子的手段。
...
<jar-file>PuPersonData.jar</jar-file>
<jar-file>PuWebTraffic.jar</jar-file>
...
在复合持久性单元的XML的定义,下面的属性需要设置
<properties>
<property name="eclipselink.composite-unit" value="true"/>
...
</properties>
此设置确保该复合持久性单元由Java EE的区别对待大于它的持久性单元成员。
在Java中
在所要存储和检索与两个人的数据和业务数据实体的Java Web应用程序使用持久性单元中,只有复合持久单元包括
@Stateless
public class DataLayer {
@PersistenceUnit(unitName="CPuPersonSessionData")
EntityManager em;
...
现在可以对包含在其中一个合成实体成员中的每个实体执行正常'em'操作,例如persist
,find
和merge
。
在Payara下,该组合持久性单元不需要XA事务来处理与每个持久性单元成员有关的实体。
的Maven
行家父 POM文件需要包含规格为有关的模块。
...
<modules>
<module>PersonData</module>
<module>WebTraffic</module>
<module>PersonSessionData</module>
</modules>
...
每个模块的POM文件需要配置为正常的Maven项目,指的是父POM文件。
陷阱:
- 您需要正确配置的Maven多模块项目,这可能有点棘手。每个复合持久性单元成员构成一个独立的Maven模块。此外,复合持久性单元是一个单独的Maven模块。成员需要先用Maven序列进行编译。
- 编译复合持久单元的模块时,需要找到复合持久单元中的'jars'。
- 每个合成持久性单元成员的实体需要在结果'jar'中直接存在于'classes'目录中(通过Maven添加到实体的额外路径是可能的但复杂的)。
- 持久性单元成员的'jars'需要在'classes'目录中可供复合持久单元找到它们。
获得的好处是一个整洁的企业数据层,可与可重用实体一起工作,每个实体都有一个中心定义。此外,可以执行跨单元原生SQL查询。我也得到了这个工作。
文档指出,当复合持久性单元成员在不同的实际数据库上运行时,跨单元本机查询将不起作用。这应该仍然被验证。
谢谢。好的,所以我必须忘记singleton和注入'EntityManagerFactory',因为我想保持容器事务的基础。所以,如果我理解的很好,你建议我把每一个新的EM都复制到每个bean中?这就是我想要避免的可维护性问题。如果不是这种情况,谢谢你的解释。 –
是的,如果您希望使用容器管理的交易,这是唯一的方法。这与在单体中声明实体管理器没什么两样。您可以应用适配器设计模式,与所有实体管理器一起开发一个独特的企业bean,而不是一个单独的企业bean(因此,当您添加或删除管理器时,您只需单点修改);这个bean实现了所有接口并将方法调用路由到其他企业bean,并将它们传递给适当的实体管理器。不幸的是,缺点是后者的企业bean方法需要将管理者作为参数。 – remigio
确定,所以其他bean将扩展我所有存储EM的独特bean?我只想要有一个独特的地方,其中EM是硬编码的。英语不是我的语言,有时我有问题来理解技术术语,原谅我。 –