当我创建复合持久性单元并尝试使用条件API时,我收到以下异常消息:
java.lang.IllegalArgumentException: No [EntityType] was found for the key class [nl.example.application.datalayer.entity.db.EntityA] in the Metamodel - please verify that the [Entity] class was referenced in persistence.xml using a specific <class>nl.example.application.datalayer.entity.db.EntityA</class> property or a global <exclude-unlisted-classes>false</exclude-unlisted-classes> element.
如果我执行jpql查询,我会得到我期望的结果。由于某种原因,元模型保持为空,如server.log中的Warning所示:
The collection of metamodel [EntityType] types is empty. Model classes may not have been found during entity search for Java SE and some Java EE container managed persistence units. Please verify that your entity classes are referenced in persistence.xml using either <class> elements or a global <exclude-unlisted-classes>false</exclude-unlisted-classes> element. The lookup on [class nl.example.application.datalayer.entity.db.EntityA] will return null.
我创建了一个应用程序的精简版本来显示问题,可以找到here。 当我使用条件API时,数据层(包含复合持久性单元)的单元测试确实给出了正确的结果,请参阅上述项目中的CompositeDAOTest。
示例项目的结构如下:
Example
|--- datalayer_project)
| |--- datalayer_parent
| | |--- pom.xml
| |
| |--- entity (some jar with entities)
| | |--- src
| | | |---main
| | | |--- java
| | | |--- resources
| | | |--- META-INF/persistence.xml
| | |--- pom.xml
| |
| |--- datalayer (the composite persistence unit to be used by the application)
| | |--- src
| | | |---main
| | | |--- java
| | | |--- resources
| | | |--- META-INF/persistence.xml
| | |--- build-jar-with-dependencies.xml (maven-assembly-plugin descriptor to build jar with all entites and their metamodel classes)
| | |--- pom.xml
| |--- pom.xml
|
|--- application (this is the example application which will be deployed)
| |--- src
| | |--- <source code>
| |--- pom.xml
|
|--- pom.xml
|--- setupServer.sh (script to create GlassFish/Payara domain)
实体jar的persistence.xml由
定义<?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="examplePU" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jta-data-source>jdbc/DataSource</jta-data-source>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<shared-cache-mode>NONE</shared-cache-mode>
<properties>
<property name="eclipselink.composite-unit.member" value="true"/>
<property name="eclipselink.logging.parameters" value="true"/>
<property name="eclipselink.target-database" value="PostgreSQL"/>
<property name="eclipselink.deploy-on-startup" value="true" />
</properties>
</persistence-unit>
复合持久性单元(datalayer)的那个:
<?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="CompositePu" transaction-type="JTA">
<provider>org.eclipse.persistence.jpa.PersistenceProvider</provider>
<jar-file>entity-${project.version}.jar</jar-file>
<exclude-unlisted-classes>false</exclude-unlisted-classes>
<properties>
<property name="eclipselink.composite-unit" value="true" />
<property name="eclipselink.logging.parameters" value="true" />
<property name="eclipselink.deploy-on-startup" value="true" />
</properties>
</persistence-unit>
</persistence>
该项目的主要部署是一场战争,其中包括一个包含复合持久性单元的胖jar和包含其元模型类的实体。 创建此应用程序的pom:
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>nl.example.application</groupId>
<artifactId>application_project</artifactId>
<version>1.0.0-SNAPSHOT</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>example</artifactId>
<packaging>war</packaging>
<name>example</name>
<dependencies>
<dependency>
<groupId>nl.example.application.datalayer</groupId>
<artifactId>datalayer</artifactId>
<version>${project.version}</version>
<classifier>jar-with-dependencies</classifier>
</dependency>
<dependency>
<groupId>de.danielbechler</groupId>
<artifactId>java-object-diff</artifactId>
<version>0.94</version>
</dependency>
<dependency>
<groupId>org.primefaces</groupId>
<artifactId>primefaces</artifactId>
<version>6.0</version>
</dependency>
<dependency>
<groupId>org.primefaces.themes</groupId>
<artifactId>all-themes</artifactId>
<version>1.0.10</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-core</artifactId>
<version>1.5.8</version>
</dependency>
<dependency>
<groupId>io.swagger</groupId>
<artifactId>swagger-jaxrs</artifactId>
<version>1.5.8</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-validator</artifactId>
<version>5.0.0.Final</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-client</artifactId>
<version>2.25.1</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.core</groupId>
<artifactId>jersey-server</artifactId>
<version>2.25.1</version>
</dependency>
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-moxy</artifactId>
<version>2.25.1</version>
</dependency>
<dependency>
<groupId>org.jboss.weld</groupId>
<artifactId>weld-core</artifactId>
<version>2.4.3.Final</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.weld.se</groupId>
<artifactId>weld-se</artifactId>
<version>2.4.3.Final</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<finalName>example</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-war-plugin</artifactId>
<configuration>
<archive>
<manifest>
<addClasspath>true</addClasspath>
<addDefaultImplementationEntries>true</addDefaultImplementationEntries>
<classpathPrefix>example/WEB-INF/lib</classpathPrefix>
</manifest>
<manifestEntries>
<git-SHA-1>${buildNumber}</git-SHA-1>
</manifestEntries>
</archive>
<failOnMissingWebXml>false</failOnMissingWebXml>
<webResources>
<webResource>
<directory>${basedir}/src/main/webapp</directory>
<filtering>true</filtering>
<includes>
<include>index.xhtml</include>
</includes>
</webResource>
</webResources>
</configuration>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>templating-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>sonar-maven-plugin</artifactId>
</plugin>
<plugin>
<groupId>org.jacoco</groupId>
<artifactId>jacoco-maven-plugin</artifactId>
<configuration>
<excludes>
<exclude>**/business/util/control/Settings**</exclude>
<exclude>**/*_*</exclude>
</excludes>
</configuration>
<executions>
<execution>
<id>jacoco-initialize</id>
<goals>
<goal>prepare-agent</goal>
</goals>
</execution>
<execution>
<id>jacoco-site</id>
<phase>package</phase>
<goals>
<goal>report</goal>
</goals>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>buildnumber-maven-plugin</artifactId>
<executions>
<execution>
<phase>validate</phase>
<goals>
<goal>create</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
<resources>
<resource>
<directory>src/main/resources</directory>
<filtering>true</filtering>
</resource>
</resources>
</build>
<scm>
<connection>scm:git:git@github.com:JCGreiner/JPACompositeAndMetaModel.git</connection>
<tag>HEAD</tag>
</scm>
</project>
为了轻松演示问题,我在应用程序中创建了3个REST端点(存储实体,findEntityNative(应该是findEntityJPQL)和findEntityCriteria),这些端点使用swagger进行记录,因此可以轻松执行。
使用该项目的步骤(也可在项目wiki here上找到):
摘要(tldr):应用程序无法找到复合持久性单元的元模型,即使jpql查询工作得很好,为什么呢?
试过了,但是没有解决方案:
1.使用来自hibernate的处理器生成元模型,如this主题中所述
2.由于使用了不同的类加载器,我尝试对CompositeDAO进行以下更改:
@PersistenceContext(unitName = "CompositePu")
protected EntityManager em;
我换成了:
private EntityManagerFactory emf;
private EntityManager em;
@PostConstruct
public void initialize() {
HashMap<String, Object> hashMap = new HashMap<>();
hashMap.put("eclipselink.classloader", this.getClass().getClassLoader());
hashMap.put("eclipselink.composite-unit", "true");
hashMap.put("eclipselink.deploy-on-startup", "true");
em = Persistence.createEntityManagerFactory("CompositePu", hashMap).createEntityManager();
if (metamodel.getManagedTypes().isEmpty()) {
logger.log(Level.WARNING, "meta model is empty");
}
不幸的是,元模型仍然是空的,上面的日志行被触发。