How to Generate the JPA Entity Metamodel

How to generate the JPA entity Metamodel?

It would be awesome if someone also knows the steps for setting this up in Eclipse (I assume it's as simple as setting up an annotation processor, but you never know)

Yes it is. Here are the implementations and instructions for the various JPA 2.0 implementations:

EclipseLink

  • org.eclipse.persistence.internal.jpa.modelgen.CanonicalModelProcessor

Hibernate

  • org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor
  • http://in.relation.to/2009/11/09/hibernate-static-metamodel-generator-annotation-processor

OpenJPA

  • org.apache.openjpa.persistence.meta.AnnotationProcessor6
  • http://openjpa.apache.org/builds/2.4.1/apache-openjpa/docs/ch13s04.html

DataNucleus

  • org.datanucleus.jpa.JPACriteriaProcessor
  • http://www.datanucleus.org/products/accessplatform_2_1/jpa/jpql_criteria_metamodel.html

The latest Hibernate implementation is available at:

  • https://mvnrepository.com/artifact/org.hibernate/hibernate-jpamodelgen/

An older Hibernate implementation is at:

  • http://repository.jboss.com/maven2/org/hibernate/hibernate-jpamodelgen/1.0.0.Final/hibernate-jpamodelgen-1.0.0.Final.jar

How to use Hibernate JPA 2 Metamodel Generator?

But when I tried to generate these metamodel by run mvn compile, it only generated corresponding classes and a strange folder 'generated-sources' in target folder as below and does not generated corresponding java files in source folder.

The default folder for the generated meta classes is ${project.build.directory}/generated-sources/apt where ${project.build.directory} is target by default. So the generated meta classes should be under target/generated-sources/apt directory (as I can guess from your screenshot the meta classes are generated).

If you want to change this behavior you can configure the plugin to generate the meta classes to another folder by using the outputDirectory element as follows:

<plugin>
<groupId>org.bsc.maven</groupId>
<artifactId>maven-processor-plugin</artifactId>
<version>3.2.0</version>
<executions>
<execution>
<id>process</id>
<goals>
<goal>process</goal>
</goals>
<phase>generate-sources</phase>
<configuration>
<processors>
<processor>org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor</processor>
</processors>
<outputDirectory>${project.basedir}/generated</outputDirectory>
</configuration>
</execution>
</executions>

And don't forget to add the new folder into your class path otherwise your project might not build.

is this expected behavior?

yes

If yes, does it mean that I need to compile code before I use metamodel each time?

yes, but if you don't change or add new entities you can use the generaed classes provided you run mvn compile at least once.

If no, how can I generate java files in source code folder?

I don't recommend to do it :-) I mean mixing the generated classes with the source code is not a good idea. If you don't like the target folder use any other folder as described above.

How to generate JPA Metamodel with Gradle 5.x

you can just remove the plugin for the jpa modelgen and just use

annotationProcessor('org.hibernate:hibernate-jpamodelgen:<version>')

Addtionally i use those settings to configure where the generated code should live.

tasks.withType(JavaCompile) {
options.annotationProcessorGeneratedSourcesDirectory = file("src/generated/java")
}

sourceSets {
generated {
java {
srcDirs = ['src/generated/java']
}
}
}

Is it possible to generate hibernate metamodel for Java 11 and java modules?

It wasn't possible, now it is possible. I opened an issue for maven-processor-plugin and they did necessary modification. So, use version 4.0-rc1+ and the following code:

        <plugin>
<groupId>org.bsc.maven</groupId>
<artifactId>maven-processor-plugin</artifactId>
<version>4.0-rc1</version>
<executions>
<execution>
<goals>
<goal>process</goal>
</goals>
<phase>generate-sources</phase>
<configuration>
<processors>
<processor>org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor</processor>
</processors>
<compilerArguments>-AaddGeneratedAnnotation=false</compilerArguments>
</configuration>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-jpamodelgen</artifactId>
<version>5.4.14.Final</version>
</dependency>
</dependencies>
</plugin>

Edit:
This is the link to the issue.

JPA Static Metamodel not recognized by IntelliJ

To get IntelliJ IDEA to recognize the generated classes, I had to add this line on build.gradle

sourceSets {
main.java.srcDirs += 'build/generated/source/apt/main'
}

Update

Better solution is to modify IntelliJ Plugin

idea {
module {
sourceDirs += file("build/generated/source/apt/main")
generatedSourceDirs += file("build/generated/source/apt/main")
}
}

Generate the JPA metamodel files using maven-processor-plugin - What is a convenient way for re-generation?

The proper solution is that generated sources should be in the target folder and shouldn't be put into the source-folders nor your SCM system.

Of course, by putting your generated sources into target, you would face the problem within your IDE because the related code can't be found. Therefore you can add the build-helper-maven-plugin to dynamically add the folder from the target directory.

<plugin>
<groupId>org.bsc.maven</groupId>
<artifactId>maven-processor-plugin</artifactId>
<executions>
<execution>
<id>process</id>
<goals>
<goal>process</goal>
</goals>
<phase>generate-sources</phase>
<configuration>
<!-- source output directory -->
<outputDirectory>${project.build.directory}/generated-sources/java/jpametamodel</outputDirectory>
<processors>
<processor>org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor</processor>
</processors>
<overwrite>true</overwrite>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>add-source</id>
<phase>generate-sources</phase>
<goals>
<goal>add-source</goal>
</goals>
<configuration>
<sources>
<source>${project.build.directory}/generated-sources/java/jpametamodel</source>
</sources>
</configuration>
</execution>
</executions>
</plugin>

hibernate jpa metamodel generator: Problem with Filer: Attempt to recreate a file for type

I made some further investigations regarding the filer problem and here is what I found out (if you are in a hurry to find out about the solution of the filer problem just jump to the bottom of this answer).

Using the following dependencies in maven triggers automatic generation of jpa static metamodel when running "mvn compile":

    <dependencies>

<dependency>
<groupId>jakarta.persistence</groupId>
<artifactId>jakarta.persistence-api</artifactId>
<version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.hibernate</groupId>
<artifactId>hibernate-jpamodelgen-jakarta</artifactId>
<scope>provided</scope>
<version>5.6.12.Final</version>
</dependency>

</dependencies>

BTW: There's really nothing else to be done for jpa static metamodel generation.

But make sure to look at the right location for the generated code. You will find it under target/generated-sources/annotations.

The filer problem occurs, if you have (a copy of) jpa static metamodel source code in your "usual" source code directory, e.g. src/main/java. You can solve this if you delete the files in the source code directory.

If your IDE now complains about unresolvable types named *_, just add target/generated-sources/annotations as source code folder in the IDE's build path.

Cheers!



Related Topics



Leave a reply



Submit