Java 在 .ear 文件中跨组件共享持久性单元
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/4073635/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Sharing a persistence unit across components in a .ear file
提问by bamoida2010
In a Java EE 6 application where I'm using .ear packaging, I'd like to create a persistence unit that can be accessed from components in different .jar files.
在我使用 .ear 打包的 Java EE 6 应用程序中,我想创建一个可以从不同 .jar 文件中的组件访问的持久性单元。
However, I'm not sure how to define this persistence unit. With the @PersistenceContext annotation the lookup only succeeds if the name matches a persistence unit defined in the local persistence.xml file.
但是,我不确定如何定义这个持久性单元。使用@PersistenceContext 注释,只有当名称与本地persistence.xml 文件中定义的持久性单元匹配时,查找才会成功。
Is it possible to refer to external persistence units?
是否可以引用外部持久性单元?
回答by Pascal Thivent
Here are the relevant sections of the JPA 2.0 specification:
以下是 JPA 2.0 规范的相关部分:
8.2 Persistence Unit Packaging
...
A persistence unit is defined by a
persistence.xml
file. The jar file or directory whoseMETA-INF
directory contains thepersistence.xml
file is termed the root of the persistence unit. In Java EE environments, the root of a persistence unit must be one of the following:
- an EJB-JAR file
- the WEB-INF/classes directory of a WAR file[80]
- a jar file in the WEB-INF/lib directory of a WAR file
- a jar file in the EAR library directory
- an application client jar file
It is not required that an EJB-JAR or WAR file containing a persistence unit be packaged in an EAR unless the persistence unit contains persistence classes in addition to those contained within the EJB-JAR or WAR. See Section 8.2.1.6.
NOTE: Java Persistence 1.0 supported use of a jar file in the root of the EAR as the root of a persistence unit. This use is no longer supported. Portable applications should use the EAR library directory for this case instead. See [9].
A persistence unit must have a name. Only one persistence unit of any given name must be defined within a single EJB-JAR file, within a single WAR file, within a single application client jar, or within an EAR. See Section 8.2.2, “Persistence Unit Scope”.
The
persistence.xml
file may be used to designate more than one persistence unit within the same scope.All persistence classes defined at the level of the Java EE EAR must be accessible to all other Java EE components in the application- i.e. loaded by the application classloader - such that if the same entity class is referenced by two different Java EE components (which may be using different persistence units), the referenced class is the same identical class.
8.2 持久化单元封装
...
持久性单元由
persistence.xml
文件定义 。jar 文件或目录META-INF
包含该persistence.xml
文件的目录称为持久性单元的根。在 Java EE 环境中,持久性单元的根必须是以下之一:
- 一个 EJB-JAR 文件
- WAR 文件的 WEB-INF/classes 目录 [80]
- WAR文件的WEB-INF/lib目录下的jar文件
- EAR 库目录中的 jar 文件
- 应用程序客户端 jar 文件
不需要将包含持久性单元的 EJB-JAR 或 WAR 文件打包到 EAR 中,除非持久性单元除了包含在 EJB-JAR 或 WAR 中的持久性类之外还包含持久性类。见第 8.2.1.6 节。
注意:Java Persistence 1.0 支持将 EAR 根目录中的 jar 文件用作持久性单元的根目录。不再支持此用途。 对于这种情况,便携式应用程序应该使用 EAR 库目录。见[9]。
持久化单元必须有一个名称。在单个 EJB-JAR 文件、单个 WAR 文件、单个应用程序客户端 jar 或 EAR 中,必须仅定义一个具有任何给定名称的持久性单元。见第 8.2.2 节,“持久性单元范围”。
该
persistence.xml
文件可用于指定同一范围内的多个持久性单元。在 Java EE EAR 级别定义的所有持久性类必须可由应用程序中的所有其他 Java EE 组件访问- 即由应用程序类加载器加载 - 这样如果两个不同的 Java EE 组件(可能使用不同的持久性单元),引用的类是相同的类。
And later:
然后:
8.2.2 Persistence Unit Scope
An EJB-JAR, WAR, application client jar, or EAR can define a persistence unit.
When referencing a persistence unit using the
unitName
annotation element orpersistence-unit-name
deployment descriptor element, the visibility scope of the persistence unit is determined by its point of definition:
- A persistence unit that is defined at the level of an EJB-JAR, WAR, or application client jar is scoped to that EJB-JAR, WAR, or application jar respectively and is visible to the components defined in that jar or war.
- A persistence unit that is defined at the level of the EAR is generally visible to all components in the application. However, if a persistence unit of the same name is defined by an EJB-JAR, WAR, or application jar file within the EAR, the persistence unit of that name defined at EAR level will not be visible to the components defined by that EJB-JAR, WAR, or application jar file unless the persistence unit reference uses the persistence unit name
#
syntax to specify a path name to disambiguate the reference.When the#
syntax is used, the path name is relative to the referencing application component jar file. For example, the syntax../lib/persistenceUnitRoot.jar#myPersistenceUnit
refers to a persistence unit whose name, as specified in the name element of thepersistence.xml
file, ismyPersistenceUnit
and for which the relative path name of the root of the persistence unit is../lib/persistenceUnitRoot.jar
. The#
syntax may be used with both theunitName
annotation element orpersistence-unit-name
deployment descriptor element to reference a persistence unit defined at EAR level.Also you need to include entity classes jar in manifest of pu jar http://wiki.eclipse.org/Packaging_and_Deploying_EclipseLink_JPA_Applications_(ELUG)
8.2.2 持久化单元范围
EJB-JAR、WAR、应用程序客户端 jar 或 EAR 可以定义持久性单元。
当使用
unitName
注释元素或persistence-unit-name
部署描述符元素引用持久性单元时,持久性单元的可见性范围由其定义点确定:
- 在 EJB-JAR、WAR 或应用程序客户端 jar 级别定义的持久性单元分别作用于该 EJB-JAR、WAR 或应用程序 jar,并且对该 jar 或 war 中定义的组件可见。
- 在 EAR 级别定义的持久性单元通常对应用程序中的所有组件可见。但是,如果 EAR 中的 EJB-JAR、WAR 或应用程序 jar 文件定义了同名的持久性单元,则在 EAR 级别定义的该名称的持久性单元对于该 EJB 定义的组件将不可见。 JAR、WAR 或应用程序 jar 文件,除非持久性单元引用使用持久性单元名称
#
语法来指定路径名以消除引用的歧义。使用该#
语法时,路径名是相对于引用应用程序组件 jar 文件的。例如,语法../lib/persistenceUnitRoot.jar#myPersistenceUnit
指的是一个持久性单元,其名称在名称的名称元素中指定persistence.xml
文件, ismyPersistenceUnit
并且持久化单元根的相对路径名是../lib/persistenceUnitRoot.jar
. 该#
语法可以与unitName
注释元素或persistence-unit-name
部署描述符元素一起使用,以引用在 EAR 级别定义的持久性单元。您还需要在 pu jar 的清单中包含实体类 jar http://wiki.eclipse.org/Packaging_and_Deploying_EclipseLink_JPA_Applications_(ELUG)
To summarize, you should be able to define your entities and the persistence unit at the top level of the EAR and to use them from the other modules.
总而言之,您应该能够在 EAR 的顶层定义您的实体和持久性单元,并在其他模块中使用它们。
I'm just not sure to understand what you tried and what problem(s) you faced.
我只是不确定您尝试了什么以及您遇到了什么问题。
回答by chrome
Here's what I did.
这就是我所做的。
1) Package the persistence configuration files in a jar file. The jar file will contain:
1)将持久化配置文件打包成jar文件。jar 文件将包含:
- META-INF/persistence.xml (and orm.xml if you use one)
- Create a "lib" folder under the EAR project and stick the jar in there
- META-INF/persistence.xml(和 orm.xml,如果你使用一个)
- 在 EAR 项目下创建一个“lib”文件夹并将 jar 粘贴在那里
2) Package the associated entity classes in another jar:
2)将关联的实体类打包到另一个jar中:
- Put this jar file in your GlassFish domain/lib folder (or whatever lib folder equiv in other servers)
- I initially bundled the jar in the EAR's "lib" folder but classes were not found
- If anyone knows a better way to handle this please explain
- 将此 jar 文件放入您的 GlassFish 域/lib 文件夹(或其他服务器中的任何 lib 文件夹等效项)
- 我最初将 jar 捆绑在 EAR 的“lib”文件夹中,但未找到类
- 如果有人知道更好的方法来处理这个请解释
The Persistence Contextshould now be accessible to all EJB and Web Apps bundled in your Enterprise Application.
在持久化上下文现在应该是所有EJB访问和Web应用程序在您的企业应用程序捆绑在一起。
回答by christian
The problem could be solved by placing a persistence.xml in a jar file that is located in the ear's lib directory.
可以通过将persistence.xml 放在位于ear 的lib 目录中的jar 文件中来解决该问题。
The persistence.xml must contain the jar files which includes the Entities. I had to give the relative path to the jar files. My ear irectory structure
persistence.xml 必须包含包含实体的 jar 文件。我必须提供 jar 文件的相对路径。我的耳朵结构
|-ear--
|-lib--|... some libs ...
| |--my-persistence-xml.jar
|-ejb-with-entities1.jar
|-ejb-with-entities2.jar
My persistence.xml for jboss 7.1.1
我的 jboss 7.1.1 的persistence.xml
<persistence-unit name="my-pu" transaction-type="JTA">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>java:jboss/datasources/mypu</jta-data-source>
<jar-file>../ejb-with-entities1.jar</jar-file>
<jar-file>../ejb-with-entities1.jar</jar-file>
<properties>
<property name="hibernate.dialect" value="org.hibernate.dialect.MySQL5Dialect"/>
<property name="hibernate.hbm2ddl.auto" value="create-drop"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true" />
</properties>
</persistence-unit>
Hope this helps
希望这可以帮助
回答by Viacheslav Dobromyslov
Example working EAR layout for Glassfish:
Glassfish 的工作 EAR 布局示例:
EAR +
|- lib +
| |- core-module.jar
| \- persistence-module.jar +
| \- META-INF +
| \- persistence.xml
|- ejb1-module.jar
\- ejb2-module.jar
EJB modules may be either jar archives or exploded directories.
EJB 模块可以是 jar 档案或分解目录。
In this case your persistence.xml
may be like:
在这种情况下,您persistence.xml
可能是这样的:
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<persistence-unit name="my-persistence-unit">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>MyDataSource</jta-data-source>
<!-- Note: it's relative to `persistence-module.jar` file location in EAR -->
<jar-file>../ejb1-module.jar</jar-file>
<jar-file>../ejb2-module.jar</jar-file>
<properties>
<property name="hibernate.current_session_context_class" value="jta"/>
<property name="hibernate.id.new_generator_mappings" value="true"/>
<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQL82Dialect"/>
<property name="hibernate.show_sql" value="true"/>
<property name="hibernate.format_sql" value="true"/>
<property name="hibernate.hbm2ddl.auto" value="update"/>
</properties>
</persistence-unit>
</persistence>
You have to update <jar-file>
references if you use module versioning (e.g. ejb1-module-1.0-SNAPSHOT.jar
).
<jar-file>
如果您使用模块版本控制(例如ejb1-module-1.0-SNAPSHOT.jar
),则必须更新引用。
Abstract objects with @MappedSuperclass
annotation and EntityManager
injection may be placed in any external jar. This jar does not require to be mentioned in persistence.xml
. For example, you can create core-module.jar
with PersistableEntity.java
:
带有@MappedSuperclass
注解和EntityManager
注入的抽象对象可以放置在任何外部 jar 中。这个 jar 不需要在persistence.xml
. 例如,您可以创建core-module.jar
具有PersistableEntity.java
:
public class PersistableEntity {
@Id
@GeneratedValue
private Long id;
public Long getId() { return id; }
public Integer getVersion() { return version; }
}
And PersistableEntityManager.java
:
并且PersistableEntityManager.java
:
public class PersistableEntityManager<T extends PersistableEntity> {
@PersistenceContext
protected EntityManager em;
}
This core-module.jar
could be used by all your projects with different persistence units.
You just inherit your Entities and EJBs and avoid boilerplate.
Check out example bilionix-core on github.
这core-module.jar
可以被具有不同持久性单元的所有项目使用。您只需继承您的实体和 EJB 并避免样板。在 github 上查看示例bilionix-core。
回答by test30
I wanted to achieve shared persistance EJB module without EAR project.
我想在没有 EAR 项目的情况下实现共享持久性 EJB 模块。
This is possible by
这是可能的
- moving all persistance entities to separate EJB project (do not move persistance.xml to new project, only classes are needed
- compiling this EJB project
- sending project to GlassFish server using
- 将所有持久性实体移动到单独的 EJB 项目(不要将 persistance.xml 移动到新项目,只需要类
- 编译这个 EJB 项目
- 使用发送项目到 GlassFish 服务器
scpAsSudo ~/NetbeansProjects/UnifyEntities/dist/UnifyEntities.jar [email protected]:/opt/glassfish3/domains/domain1/lib/ext
Have fun!
玩得开心!
回答by jprism
All you need
一切你需要的
EAR +
|- META-INF +
| - persistence.xml
|- ejb1-module.jar
|- ejb2-module.jar
<?xml version="1.0" encoding="UTF-8"?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence" version="2.0">
<persistence-unit name="my-persistence-unit">
<provider>org.hibernate.ejb.HibernatePersistence</provider>
<jta-data-source>MyDataSource</jta-data-source>
<!-- Note: it's relative to `persistence-module.jar` file location in EAR -->
<jar-file>../ejb1-module.jar</jar-file>
<jar-file>../ejb2-module.jar</jar-file>
<properties>
...
</properties>
</persistence-unit>
</persistence>
回答by Juan Rodriguez
Try with this:
试试这个:
Configure EAR application.xml file in this way:
http://xmlns.jcp.org/xml/ns/javaee/application_7.xsd" version="7"> YourEEApplication
<initialize-in-order>true</initialize-in-order> <!-- This is the most important thing --> <module> <ejb>YourEJBModule1.jar</ejb> </module> <module> <ejb>YourEJBModule2.jar</ejb> </module> ...... <module> <ejb>YourEJBModuleX.jar</ejb> </module> <module> <web> <web-uri>YourWebModule.war</web-uri> <context-root>YourWebModule</context-root> </web> </module>
In your EJB projects YourEJBModule1, YourEJBModule2... and YourEJBModuleX:
以这种方式配置 EAR application.xml 文件:
http://xmlns.jcp.org/xml/ns/javaee/application_7.xsd" version="7"> YourEEApplication
<initialize-in-order>true</initialize-in-order> <!-- This is the most important thing --> <module> <ejb>YourEJBModule1.jar</ejb> </module> <module> <ejb>YourEJBModule2.jar</ejb> </module> ...... <module> <ejb>YourEJBModuleX.jar</ejb> </module> <module> <web> <web-uri>YourWebModule.war</web-uri> <context-root>YourWebModule</context-root> </web> </module>
在您的 EJB 项目 YourEJBModule1、YourEJBModule2... 和 YourEJBModuleX 中:
Inject Persistence Context whitout the unitName property:
在没有 unitName 属性的情况下注入持久化上下文:
@PersistenceContext(type=PersistenceContextType.TRANSACTION)
private EntityManager em; // get & set
- For each EJB module persistence.xml file:
- 对于每个 EJB 模块 persistence.xml 文件:
YourEJBModule1:
你的EJBModule1:
<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.1"
xmlns="http://xmlns.jcp.org/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/persistence http://xmlns.jcp.org/xml/ns/persistence/persistence_2_1.xsd">
<persistence-unit name="PersistenceUnit1"
transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/YourDataSource</jta-data-source>
<class>com.example.Foo1</class>
<!-- Other properties -->
</persistence-unit>
</persistence>
YourEJBModule2:
你的EJBModule2:
<?xml version="1.0" encoding="UTF-8"?>
...
<persistence-unit name="PersistenceUnit2"
transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/YourDataSource</jta-data-source>
<jar-file>YourEJBModule1.jar</jar-file>
<class>com.example.Foo2</class>
<!-- Other properties -->
</persistence-unit>
...
YourEJBModuleX:
你的EJBModuleX:
<?xml version="1.0" encoding="UTF-8"?>
...
<persistence-unit name="PersistenceUnitX"
transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/YourDataSource</jta-data-source>
<jar-file>YourEJBModule1.jar</jar-file>
<jar-file>YourEJBModule2.jar</jar-file>
......
<class>com.example.FooX</class>
<!-- Other properties -->
</persistence-unit>
...
In the database can exists various schemas, one per EJB module, access them through jta-data-source
数据库中可以存在各种模式,每个EJB模块一个,通过jta-data-source访问它们
(Deployed in Glassfish 4)
(在 Glassfish 4 中部署)