在 .ear 文件中跨组件共享持久性单元

发布于 2024-09-30 08:43:17 字数 192 浏览 2 评论 0原文

在我使用 .ear 打包的 Java EE 6 应用程序中,我想创建一个可以从不同 .jar 文件中的组件访问的持久性单元。

但是,我不确定如何定义这个持久性单元。使用 @PersistenceContext 注释,仅当名称与本地 persistence.xml 文件中定义的持久性单元匹配时,查找才会成功。

是否可以引用外部持久性单元?

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.

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.

Is it possible to refer to external persistence units?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(7

陌上青苔 2024-10-07 08:43:17

以下是 JPA 2.0 规范的相关部分:

8.2 持久化单元打包

...

持久性单元由
persistence.xml 文件。 jar 文件或
META-INF 目录的目录
包含 persistence.xml 文件是
称为坚持之根
单元。在 Java EE 环境中,
持久化单元的根必须是1
以下内容:

  • 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 支持在根目录中使用 jar 文件
EAR 作为持久性单元的根。
不再支持此用途。
对于这种情况,便携式应用程序应使用 EAR 库目录
相反。参见[9]。

持久性单元必须有一个名称。
任何给定的只有一个持久性单元
名称必须在单个名称中定义
EJB-JAR 文件,在单个 WAR 中
文件,在单个应用程序中
客户端 jar 或 EAR 内。看
第 8.2.2 节 “持久化单元
范围”。

可以使用persistence.xml文件
指定多个持久性
同一范围内的单位。

定义在的所有持久性类
Java EE EAR 的级别必须是
所有其他 Java EE 均可访问
应用程序中的组件
- 即
由应用程序类加载器加载
- 这样如果同一个实体类被两个不同的Java EE引用
组件(可能使用
不同的持久性单位),
引用的类是相同的
类。

后来:

8.2.2 持久化单元范围

EJB-JAR、WAR、应用程序客户端
jar,或者EAR可以定义持久性
单位。

引用持久性单元时
使用 unitName 注释
元素或持久性单元名称
部署描述符元素,
持久化可见范围
单位由其点确定
定义:

  • 在 EJB-JAR、WAR 或 EJB-JAR 级别定义的持久性单元
    应用程序客户端 jar 的范围是
    EJB-JAR、WAR 或应用程序 jar
    分别可见
    在该 jar 或 war 中定义的组件。
  • 在 EAR 级别定义的持久性单元通常是
    对所有组件可见
    应用程序。然而,如果坚持
    同名的单位由一个定义
    EJB-JAR、WAR 或应用程序 jar 文件
    在 EAR 中,持久性单元
    在 EAR 级别定义的名称将
    对组件不可见
    由该 EJB-JAR、WAR 或
    应用程序 jar 文件,除非
    持久性单元参考使用
    持久化单元名称 # 语法
    指定一个路径名以消除歧义
    引用。
    # 语法为
    使用时,路径名是相对于
    引用应用程序组件 jar
    文件。例如,语法
    ../lib/persistenceUnitRoot.jar#myPersistenceUnit
    指的是一个持久性单元,其
    名称,如名称元素中所指定
    persistence.xml 文件的内容是
    myPersistenceUnit 以及
    根目录的相对路径名
    持久性单位是
    ../lib/persistenceUnitRoot.jar。这
    # 语法可以与 unitName 注释元素或
    持久性单元名称部署
    引用 a 的描述符元素
    在 EAR 级别定义的持久性单元。

您还需要在 pu jar 的清单中包含实体类 jar http://wiki.eclipse.org/Packaging_and_Deploying_EclipseLink_JPA_Applications_(ELUG )

总而言之,您应该能够在 EAR 的顶层定义您的实体和持久性单元,并在其他模块中使用它们。

我只是不确定您尝试了什么以及您遇到了什么问题。

Here are the relevant sections of the JPA 2.0 specification:

8.2 Persistence Unit Packaging

...

A persistence unit is defined by a
persistence.xml file. The jar file or
directory whose META-INF directory
contains the persistence.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.

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 or persistence-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 the persistence.xml file, is
    myPersistenceUnit 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 the unitName annotation element or
    persistence-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)

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.

I'm just not sure to understand what you tried and what problem(s) you faced.

紙鸢 2024-10-07 08:43:17

该问题可以通过将 persistence.xml 放入位于ear 的lib 目录中的jar 文件中来解决。

persistence.xml 必须包含包含实体的 jar 文件。
我必须提供 jar 文件的相对路径。
我的耳朵目录结构

|-ear--
       |-lib--|... some libs ...
       |      |--my-persistence-xml.jar
       |-ejb-with-entities1.jar
       |-ejb-with-entities2.jar

我的 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>

希望这有帮助

The problem could be solved by placing a persistence.xml in a jar file that is located in the ear's lib directory.

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

|-ear--
       |-lib--|... some libs ...
       |      |--my-persistence-xml.jar
       |-ejb-with-entities1.jar
       |-ejb-with-entities2.jar

My persistence.xml for jboss 7.1.1

<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

凉墨 2024-10-07 08:43:17

所有你需要的

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>

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>
甜心小果奶 2024-10-07 08:43:17

Glassfish 的工作 EAR 布局示例:

EAR +
    |- lib +
    |      |- core-module.jar
    |      \- persistence-module.jar +
    |                                 \- META-INF +
    |                                              \- persistence.xml
    |- ejb1-module.jar
    \- ejb2-module.jar

EJB 模块可以是 jar 档案或分解目录。

在这种情况下,您的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>

如果您使用模块版本控制(例如ejb1-module-),则必须更新引用1.0-SNAPSHOT.jar)。

带有@MappedSuperclass 注释和EntityManager 注入的抽象对象可以放置在任何外部jar 中。这个 jar 不需要在 persistence.xml 中提及。例如,您可以使用 PersistableEntity.java 创建 core-module.jar

public class PersistableEntity {
    @Id
    @GeneratedValue
    private Long id;

    public Long getId() { return id; }

    public Integer getVersion() { return version; }
}

PersistableEntityManager.java

public class PersistableEntityManager<T extends PersistableEntity> {
    @PersistenceContext
    protected EntityManager em;
}

core-module。 jar 可以被具有不同持久性单元的所有项目使用。
您只需继承实体和 EJB 并避免样板文件。
查看 github 上的 bilionix-core 示例。

Example working EAR layout for Glassfish:

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.

In this case your persistence.xml may be like:

<?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).

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:

public class PersistableEntity {
    @Id
    @GeneratedValue
    private Long id;

    public Long getId() { return id; }

    public Integer getVersion() { return version; }
}

And 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.

清风夜微凉 2024-10-07 08:43:17

尝试这样做:

  1. 以这种方式配置 EAR application.xml 文件:

    http://xmlns.jcp.org/xml/ns/javaee/application_7.xsd”
    版本=“7”>
    您的EE应用程序

    <按顺序初始化>true <!-- 这是最重要的-->
    
    <模块>
        YourEJBModule1.jar
    
    <模块>
        YourEJBModule2.jar
    
    ......
    <模块>
        YourEJBModuleX.jar
    
    
    <模块>
        <网络>
            YourWebModule.war;
            YourWebModule
        
    
    

  2. 在您的 EJB 项目 YourEJBModule1、YourEJBModule2... 和 YourEJBModuleX 中:

注入 Persistence Context,不带 unitName 属性:

@PersistenceContext(type=PersistenceContextType.TRANSACTION)
    private EntityManager em; // get & set
  1. 对于每个 EJB 模块 persistence.xml 文件:

YourEJBModule1:

<?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:

<?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:

<?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>
...

数据库中可以存在各种模式,每个 EJB 模块一个,通过 jta-data-source 访问它们

(部署在 Glassfish 4 中)

Try with this:

  1. 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>
    

  2. In your EJB projects YourEJBModule1, YourEJBModule2... and YourEJBModuleX:

Inject Persistence Context whitout the unitName property:

@PersistenceContext(type=PersistenceContextType.TRANSACTION)
    private EntityManager em; // get & set
  1. For each EJB module persistence.xml file:

YourEJBModule1:

<?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:

<?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:

<?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

(Deployed in Glassfish 4)

勿忘初心 2024-10-07 08:43:17

这就是我所做的。

1)将持久化配置文件打包为jar文件。 jar 文件将包含:

  • META-INF/persistence.xml (以及 orm.xml,如果您使用的话)
  • 在 EAR 项目下创建一个“lib”文件夹并将 jar 粘贴到其中

2) 打包另一个 jar 中的关联实体类:

  • 将此 jar 文件放入您的 GlassFish 域/lib 文件夹(或其他服务器中的任何 lib 文件夹中)
  • 我最初将该 jar 捆绑在 EAR 的“lib”文件夹中,但未找到类
  • 如果有人知道更好的方法来处理此问题,请解释一下

持久性上下文现在应该可供企业应用程序中捆绑的所有 EJB 和 Web 应用程序访问。

Here's what I did.

1) Package the persistence configuration files in a jar file. The jar file will contain:

  • 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

2) Package the associated entity classes in another 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

The Persistence Context should now be accessible to all EJB and Web Apps bundled in your Enterprise Application.

请恋爱 2024-10-07 08:43:17

我想在没有 EAR 项目的情况下实现共享持久性 EJB 模块。

这可以通过将

  1. 所有持久性实体移动到单独的 EJB 项目来实现(不要将 persistance.xml 移动到新项目,只需要
  2. 编译此 EJB 项目的
  3. 将项目发送到 GlassFish 服务器)
scpAsSudo ~/NetbeansProjects/UnifyEntities/dist/UnifyEntities.jar [email protected]:/opt/glassfish3/domains/domain1/lib/ext

类,使用Have fun!

I wanted to achieve shared persistance EJB module without EAR project.

This is possible by

  1. moving all persistance entities to separate EJB project (do not move persistance.xml to new project, only classes are needed
  2. compiling this EJB project
  3. sending project to GlassFish server using
scpAsSudo ~/NetbeansProjects/UnifyEntities/dist/UnifyEntities.jar [email protected]:/opt/glassfish3/domains/domain1/lib/ext

Have fun!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文