gpt4 book ai didi

jpa - 在共享 JAR 的 persistence.xml 中使用 EAR 级别定义的数据源作为 JTA 数据源

转载 作者:行者123 更新时间:2023-12-04 15:23:37 25 4
gpt4 key购买 nike

在 Jakarta EE 8 环境中:是否可以在 EAR 级别定义(“可移植 JNDI”)数据源 [ 1 ] 在 application.xml 中并将此数据源用作库/JAR 模块内 persistence.xml 中的 JTA 数据源?

目的:创建一个通用的 JAR 模块,它定义了 JPA 实体和相应的“存储库”,以便这个 JAR 模块可以被多个 WAR 模块(例如,一个 RESTful API 和一个 UI 模块)使用,并将这个模块打包为一个 EAR可部署到多个应用程序服务器

使用以下尝试/方法(作为完整示例,我创建了一个简单的 git 存储库 [ 2 ]),此类 EAR 的部署失败了(至少对于 Payara 和 WildFly)。


尝试/方法

假设有一个由 2 个 WAR 模块组成的应用程序,并且两个 WAR 模块都使用一个共享的 JAR 模块,因此应用程序结构如下所示:

ear/
├── shared-lib-jar
| ├── ...
| └── META-INF
| ├── ...
| └── persistence.xml
├── api-war/
| └── ...
├── ui-war/
| └── ...
├── application.xml
├── ...

在 EAR 的 application.xml 中,数据源定义如下:

<application>
<!-- ... -->
<data-source>
<name>java:app/appDS</name>
<!-- ... -->
</data-source>
</application>

persistence.xml 中,在 application.xml 中定义的 JNDI 名称用作 JTA 数据源:

<persistence>
<persistence-unit name="..." transaction-type="JTA">
<jta-data-source>java:app/appDS</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<!-- ... -->
</persistence-unit>
</persistence>

不同 (2) 应用程序服务器的意外/故障行为/情况

设置:org.h2.jdbcx.JdbcDataSource 作为class-name 和“基于文件的”数据库

Payara (5.2020.2)

不会创建数据库文件并且服务器日志显示:

[2020-07-07T22:56:32.731+0200] [Payara 5.2020] [SEVERE] [AS-DEPLOYMENT-00026] [javax.enterprise.system.tools.deployment.dol] [tid: _ThreadID=168 _ThreadName=admin-thread-pool::admin-listener(11)] [timeMillis: 1594155392731] [levelValue: 1000] [[
JNDI lookup failed for the resource: Name: foo-core, Lookup: java:app/appDS, Type: javax.sql.DataSource.]]

[2020-07-07T22:56:32.731+0200] [Payara 5.2020] [SEVERE] [] [javax.enterprise.system.core] [tid: _ThreadID=168 _ThreadName=admin-thread-pool::admin-listener(11)] [timeMillis: 1594155392731] [levelValue: 1000] [[
JNDI lookup failed for the resource: Name: [foo-core], Lookup: [java:app/appDS], Type: [javax.sql.DataSource]]]

WildFly(1.4.11.Final)

数据库文件已创建,但服务器日志显示:

{"WFLYCTL0062: Composite operation failed and was rolled back. Steps that failed:" => {"Operation step-2" => {"WFLYCTL0080: Failed services" => {"jboss.deployment.unit.\"foo-ear-0.0.1-SNAPSHOT.ear\".WeldStartService" => "Failed to start service
Caused by: java.lang.IllegalArgumentException: WFLYWELD0037: Error injecting persistence unit into CDI managed bean. Can't find a persistence unit named 'foo-core' in deployment foo-ear-0.0.1-SNAPSHOT.ear for injection point protected javax.persistence.EntityManager com.acme.BookRepository.entityManager"}}}}

1:https://jakarta.ee/specifications/platform/8/platform-spec-8.html#a1688

2:https://gitlab.com/hjoeren/application-level-ds-example

最佳答案

是的,您几乎完成了,至少在 Payara 或 Glasshish 的情况下是这样。您不需要在 application.xml 中公开您的数据源。

首先像您所做的那样在 persistence.xml 中声明您的数据源:

<?xml version="1.0" encoding="UTF-8"?>
<persistence version="2.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd">
<persistence-unit name="my.PU" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
**<jta-data-source>jdbc/mydatasource</jta-data-source>**
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="eclipselink.logging.level" value="INFO"/>
<property name="eclipselink.logging.parameters" value="true"/>
<property name="eclipselink.persistence-context.flush-mode" value="COMMIT"/>
</properties>
</persistence-unit>
</persistence>

然后只需使用管理控制台或 asadmin 命令在您的 Payara(或 GF)应用程序服务器上配置适当的连接池和 JDBC 资源。 glassfish-resources.xml 文件示例

$cat glassfish-resources.xml
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE resources PUBLIC "-//GlassFish.org//DTD GlassFish Application Server 3.1 Resource Definitions//EN" "http://glassfish.org/dtds/glassfish-resources_1_5.dtd">
<resources>
<jdbc-connection-pool connection-creation-retry-interval-in-seconds="30" connection-validation-method="auto-commit" datasource-classname="com.mysql.jdbc.jdbc2.optional.MysqlDataSource" wrap-jdbc-objects="false" res-type="javax.sql.DataSource" `name="mysql_myrootPool"` is-connection-validation-required="true" connection-creation-retry-attempts="10" validate-atmost-once-period-in-seconds="60">
<property name="User" value="root"/>
<property name="Password" value="secret"/>
<property name="URL" value="jdbc:mysql://localhost:3306/mydb?zeroDateTimeBehavior=convertToNull"/>
<property name="driverClass" value="com.mysql.jdbc.Driver"/>
<property name="zeroDateTimeBehavior" value="convertToNull"/>
<property name="characterEncoding" value="utf-8"/>
<property name="useSSL" value="false"/>
</jdbc-connection-pool>
<jdbc-resource enabled="true" `jndi-name="jdbc/mydatasource"` object-type="user" `pool-name="mysql_myrootPool"`/>
</resources>
$asadmin add-resources glassfish-resources.xml

请注意池、持久性单元和资源的正确名称。

现在您可以像这样在您的 EAR 中包含的任何 EJB 或 WEB 模块中允许的任何地方(EJB、Servlet、拦截器等)注入(inject)您的连接

@PersistenceContext(unitName = "my.PU")
private EntityManager em;

关于jpa - 在共享 JAR 的 persistence.xml 中使用 EAR 级别定义的数据源作为 JTA 数据源,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/62784298/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com