如何在 WebSphere Liberty 上通过 JPA 使用 H2 数据库
How to use H2 database with JPA on WebSphere Liberty
我在 WebSphere Application Server 18.0.0.2
上有一个非常简单的 Web 应用程序 运行ning。该应用程序被打包到 WAR 并放在 dropins
下(为简单起见)。
我的 server.xml
看起来像这样:
<?xml version="1.0" encoding="UTF-8"?>
<server description="new server">
<featureManager>
<feature>javaee-8.0</feature>
</featureManager>
<httpEndpoint id="defaultHttpEndpoint" httpPort="9080" httpsPort="9443" />
<!-- Automatically expand WAR files and EAR files -->
<applicationManager autoExpand="true"/>
<!-- THE JAR IS THERE (UNDER Liberty lib directory) -->
<library id="H2JDBCLib">
<fileset dir="${wlp.install.dir}/lib" includes="h2-1.4.197.jar"/>
</library>
<!-- AND THIS IS MY DATA SOURCE DEFINITION -->
<dataSource id="h2test" jndiName="jdbc/h2test">
<jdbcDriver libraryRef="H2JDBCLib"/>
<properties.db2.jcc databaseName="testdb" serverName="localhost" portNumber="8082" user="sa" />
</dataSource>
</server>
我有一个非常简单的实体和一个服务(无状态 EJB):
@Stateless
public class CustomerService {
@PersistenceContext(unitName = "h2test")
private EntityManager entityManager;
public List<Customer> getAllCustomers() {
return entityManager
.createNamedQuery(FIND_ALL, Customer.class)
.getResultList();
}
}
我的 persistence.xml
在 META-INF 下看起来像这样:
<?xml version="1.0" encoding="UTF-8"?>
<persistence 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_1_0.xsd"
version="1.0">
<persistence-unit name="h2test" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/h2test</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
</persistence-unit>
</persistence>
我认为这些简单的配置应该足以部署和 运行 这个 hello-world 类型的应用程序。但是我在 运行 时间收到一个错误:
[ERROR ] CNTR0019E: EJB throws an exception when invoking "getAllCustomers".
Details: javax.ejb.EJBException: The java:comp/env/com.my.app.service.CustomerService/entityManager reference of type javax.persistence.EntityManager for the null component in the my-app.war module of the my-app application cannot be resolved.
at com.ibm.wsspi.injectionengine.InjectionBinding.getInjectionObject(InjectionBinding.java:1489)
at [internal classes]
at com.my.app.service.EJSLocalNSLCustomerService_22d8d9f5.getAllCustomers(EJSLocalNSLCustomerService_22d8d9f5.java)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
EntityManager 注入失败。从 IBM 的文档中不清楚还应该做什么。
我的应用程序中没有其他 XML 文件(配置文件)。
我是不是漏掉了什么?
我看到的主要问题是 server.xml 中的 <datasource>
定义,您使用了 <properties.db2.jcc>
元素,它对应于 IBM DB2 JCC JDBC 驱动程序。由于 Liberty 没有专用的 <properties.h2>
配置,您必须使用通用 <properties>
配置元素,并在 <jdbcDriver>
元素上定义 DataSource class 名称。
配置应如下所示:
<dataSource id="h2test" jndiName="jdbc/h2test">
<!-- Define the DataSource class names on the <jdbcDriver> element -->
<jdbcDriver
javax.sql.XADataSource="org.h2.jdbcx.JdbcDataSource"
javax.sql.ConnectionPoolDataSource="org.h2.jdbcx.JdbcDataSource"
javax.sql.DataSource="org.h2.jdbcx.JdbcDataSource"
libraryRef="H2JDBCLib"/>
<!-- set the connection URL on the <properties> element.
this corresponds to the setURL() method on H2's JdbcDataSource class.
you may also list any properties here that have a corresponding setXXX method on H2's JdbcDataSource class -->
<properties URL="jdbc:h2:mem:testdb"/>
</dataSource>
此外,如果您将 H2 JDBC 驱动程序放在 ${server.config.dir}
或 ${shared.resource.dir}
下的某处会更好,因为 ${wlp.install.dir}/lib
是 Liberty 运行时的 jar 所在的位置.您不想将您的应用程序 jar 与那些混在一起!
<library id="H2JDBCLib">
<fileset dir="${server.config.dir}" includes="h2-1.4.197.jar"/>
</library>
最后,确保您的 persistence.xml 文件位于 WAR 应用程序中的正确位置。它应该在 WEB-INF/classes/META-INF/persistence.xml
作为中间调试步骤,您可以检查以确保数据源可以从您的应用程序中解析,如下所示:
@Resource(lookup = "jdbc/h2test")
DataSource ds;
// ...
ds.getConnection().close();
一旦你让那个部分开始工作,就开始注射你的 EntityManager
。此外,如果出现问题,请务必检查 ${server.config.dir}/logs/messages.log
以获得更详细的错误消息。
我在 WebSphere Application Server 18.0.0.2
上有一个非常简单的 Web 应用程序 运行ning。该应用程序被打包到 WAR 并放在 dropins
下(为简单起见)。
我的 server.xml
看起来像这样:
<?xml version="1.0" encoding="UTF-8"?>
<server description="new server">
<featureManager>
<feature>javaee-8.0</feature>
</featureManager>
<httpEndpoint id="defaultHttpEndpoint" httpPort="9080" httpsPort="9443" />
<!-- Automatically expand WAR files and EAR files -->
<applicationManager autoExpand="true"/>
<!-- THE JAR IS THERE (UNDER Liberty lib directory) -->
<library id="H2JDBCLib">
<fileset dir="${wlp.install.dir}/lib" includes="h2-1.4.197.jar"/>
</library>
<!-- AND THIS IS MY DATA SOURCE DEFINITION -->
<dataSource id="h2test" jndiName="jdbc/h2test">
<jdbcDriver libraryRef="H2JDBCLib"/>
<properties.db2.jcc databaseName="testdb" serverName="localhost" portNumber="8082" user="sa" />
</dataSource>
</server>
我有一个非常简单的实体和一个服务(无状态 EJB):
@Stateless
public class CustomerService {
@PersistenceContext(unitName = "h2test")
private EntityManager entityManager;
public List<Customer> getAllCustomers() {
return entityManager
.createNamedQuery(FIND_ALL, Customer.class)
.getResultList();
}
}
我的 persistence.xml
在 META-INF 下看起来像这样:
<?xml version="1.0" encoding="UTF-8"?>
<persistence 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_1_0.xsd"
version="1.0">
<persistence-unit name="h2test" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/h2test</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
</persistence-unit>
</persistence>
我认为这些简单的配置应该足以部署和 运行 这个 hello-world 类型的应用程序。但是我在 运行 时间收到一个错误:
[ERROR ] CNTR0019E: EJB throws an exception when invoking "getAllCustomers".
Details: javax.ejb.EJBException: The java:comp/env/com.my.app.service.CustomerService/entityManager reference of type javax.persistence.EntityManager for the null component in the my-app.war module of the my-app application cannot be resolved.
at com.ibm.wsspi.injectionengine.InjectionBinding.getInjectionObject(InjectionBinding.java:1489)
at [internal classes]
at com.my.app.service.EJSLocalNSLCustomerService_22d8d9f5.getAllCustomers(EJSLocalNSLCustomerService_22d8d9f5.java)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
EntityManager 注入失败。从 IBM 的文档中不清楚还应该做什么。
我的应用程序中没有其他 XML 文件(配置文件)。
我是不是漏掉了什么?
我看到的主要问题是 server.xml 中的 <datasource>
定义,您使用了 <properties.db2.jcc>
元素,它对应于 IBM DB2 JCC JDBC 驱动程序。由于 Liberty 没有专用的 <properties.h2>
配置,您必须使用通用 <properties>
配置元素,并在 <jdbcDriver>
元素上定义 DataSource class 名称。
配置应如下所示:
<dataSource id="h2test" jndiName="jdbc/h2test">
<!-- Define the DataSource class names on the <jdbcDriver> element -->
<jdbcDriver
javax.sql.XADataSource="org.h2.jdbcx.JdbcDataSource"
javax.sql.ConnectionPoolDataSource="org.h2.jdbcx.JdbcDataSource"
javax.sql.DataSource="org.h2.jdbcx.JdbcDataSource"
libraryRef="H2JDBCLib"/>
<!-- set the connection URL on the <properties> element.
this corresponds to the setURL() method on H2's JdbcDataSource class.
you may also list any properties here that have a corresponding setXXX method on H2's JdbcDataSource class -->
<properties URL="jdbc:h2:mem:testdb"/>
</dataSource>
此外,如果您将 H2 JDBC 驱动程序放在 ${server.config.dir}
或 ${shared.resource.dir}
下的某处会更好,因为 ${wlp.install.dir}/lib
是 Liberty 运行时的 jar 所在的位置.您不想将您的应用程序 jar 与那些混在一起!
<library id="H2JDBCLib">
<fileset dir="${server.config.dir}" includes="h2-1.4.197.jar"/>
</library>
最后,确保您的 persistence.xml 文件位于 WAR 应用程序中的正确位置。它应该在 WEB-INF/classes/META-INF/persistence.xml
作为中间调试步骤,您可以检查以确保数据源可以从您的应用程序中解析,如下所示:
@Resource(lookup = "jdbc/h2test")
DataSource ds;
// ...
ds.getConnection().close();
一旦你让那个部分开始工作,就开始注射你的 EntityManager
。此外,如果出现问题,请务必检查 ${server.config.dir}/logs/messages.log
以获得更详细的错误消息。