HHH-15170 - Dedicated chapter for "Build Tool Support"
HHH-15171 - Add discussion of the Ant Plugin
This commit is contained in:
parent
cf152d57b1
commit
17bb4aa066
|
@ -1,442 +0,0 @@
|
||||||
[[jpamodelgen-guide]]
|
|
||||||
= Jakarta Persistence Static Metamodel Generator
|
|
||||||
:imagesdir: images
|
|
||||||
:version: {fullVersion}
|
|
||||||
:toc:
|
|
||||||
|
|
||||||
[[whatisit]]
|
|
||||||
== What is it about?
|
|
||||||
|
|
||||||
Jakarta Persistence defines a typesafe Criteria API which allows `Criteria` queries
|
|
||||||
to be constructed in a strongly-typed manner, utilizing so called
|
|
||||||
static metamodel classes.
|
|
||||||
For developers it is important that the task of the metamodel generation
|
|
||||||
can be automated.
|
|
||||||
Hibernate Static Metamodel Generator is an annotation processor based on
|
|
||||||
https://jcp.org/en/jsr/detail?id=269[JSR_269] with the task of creating Jakarta Persistence 2
|
|
||||||
static metamodel classes.
|
|
||||||
The following example shows two native-bootstrap entities `Order` and `Item`, together
|
|
||||||
with the metamodel class `Order_` and a typesafe query.
|
|
||||||
|
|
||||||
[[jpa2-entity-example]]
|
|
||||||
.Jakarta Persistence annotated entities `Order` and `Item`
|
|
||||||
|
|
||||||
====
|
|
||||||
[source, JAVA]
|
|
||||||
----
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
public class Order {
|
|
||||||
@Id
|
|
||||||
@GeneratedValue
|
|
||||||
Integer id;
|
|
||||||
|
|
||||||
@ManyToOne
|
|
||||||
Customer customer;
|
|
||||||
|
|
||||||
@OneToMany
|
|
||||||
Set<Item> items;
|
|
||||||
BigDecimal totalCost;
|
|
||||||
|
|
||||||
// standard setter/getter methods
|
|
||||||
...
|
|
||||||
}
|
|
||||||
|
|
||||||
@Entity
|
|
||||||
public class Item {
|
|
||||||
@Id
|
|
||||||
@GeneratedValue
|
|
||||||
Integer id;
|
|
||||||
|
|
||||||
int quantity;
|
|
||||||
|
|
||||||
@ManyToOne
|
|
||||||
Order order;
|
|
||||||
|
|
||||||
// standard setter/getter methods
|
|
||||||
...
|
|
||||||
}
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
====
|
|
||||||
[[metamodel-class-example]]
|
|
||||||
.Metamodel class Order_
|
|
||||||
|
|
||||||
====
|
|
||||||
[source, JAVA]
|
|
||||||
----
|
|
||||||
|
|
||||||
@StaticMetamodel(Order.class)
|
|
||||||
public class Order_ {
|
|
||||||
public static volatile SingularAttribute<Order, Integer> id;
|
|
||||||
public static volatile SingularAttribute<Order, Customer> customer;
|
|
||||||
public static volatile SetAttribute<Order, Item> items;
|
|
||||||
public static volatile SingularAttribute<Order, BigDecimal> totalCost;
|
|
||||||
}
|
|
||||||
|
|
||||||
----
|
|
||||||
|
|
||||||
====
|
|
||||||
[[criteria-example]]
|
|
||||||
.Typesafe citeria query
|
|
||||||
|
|
||||||
====
|
|
||||||
[source, JAVA]
|
|
||||||
----
|
|
||||||
CriteriaBuilder cb = entityManager.getCriteriaBuilder();
|
|
||||||
|
|
||||||
CriteriaQuery<Order> cq = cb.createQuery(Order.class);
|
|
||||||
|
|
||||||
SetJoin<Order, Item> itemNode = cq.from(Order.class).join(Order_.items);
|
|
||||||
|
|
||||||
cq.where( cb.equal(itemNode.get(Item_.id), 5 ) ).distinct(true);
|
|
||||||
----
|
|
||||||
|
|
||||||
====
|
|
||||||
|
|
||||||
[TIP]
|
|
||||||
====
|
|
||||||
Hibernate Static Metamodel Generator also takes into consideration xml
|
|
||||||
configuration specified in `orm.xml` or mapping files specified in
|
|
||||||
`persistence.xml`. However, if XML is your only configuration source,
|
|
||||||
you need to add in at least on of the mapping file the following
|
|
||||||
persistence unit metadata:
|
|
||||||
----
|
|
||||||
<persistence-unit-metadata>
|
|
||||||
<xml-mapping-metadata-complete/>
|
|
||||||
</persistence-unit-metadata>
|
|
||||||
----
|
|
||||||
====
|
|
||||||
|
|
||||||
== Canonical Metamodel
|
|
||||||
|
|
||||||
The structure of the metamodel classes is described in the Jakarta Persistence
|
|
||||||
(JSR 317) https://jcp.org/en/jsr/detail?id=317[specification], but for
|
|
||||||
completeness the definition is repeated in the following paragraphs.
|
|
||||||
Feel free to skip ahead to the <<chapter-usage,usage chapter>>, if you
|
|
||||||
are not interested into the gory details.
|
|
||||||
|
|
||||||
The annotation processor produces for every managed entity in the
|
|
||||||
persistence unit a metamodel class based on these rules:
|
|
||||||
|
|
||||||
* For each managed class X in package p, a metamodel class X_ in
|
|
||||||
package p is created.
|
|
||||||
|
|
||||||
* The name of the metamodel class is derived from the name of the
|
|
||||||
managed class by appending "_" to the name of the managed class.
|
|
||||||
|
|
||||||
* The metamodel class X_ must be annotated with the
|
|
||||||
`jakarta.persistence.StaticMetamodel` annotation.
|
|
||||||
|
|
||||||
* If class X extends another class S, where S is the most derived
|
|
||||||
managed class (i.e., entity or mapped superclass) extended by X, then
|
|
||||||
class X_ must extend class S_, where S_ is the metamodel class created
|
|
||||||
for S.
|
|
||||||
|
|
||||||
* For every persistent non-collection-valued attribute y declared by
|
|
||||||
class X, where the type of y is Y, the metamodel class must contain a
|
|
||||||
declaration as follows:
|
|
||||||
|
|
||||||
public static volatile SingularAttribute<X, Y> y;
|
|
||||||
|
|
||||||
* For every persistent collection-valued attribute z declared by class
|
|
||||||
X, where the element type of z is Z, the metamodel class must contain
|
|
||||||
a declaration as follows:
|
|
||||||
** if the collection type of z is java.util.Collection, then
|
|
||||||
|
|
||||||
public static volatile CollectionAttribute<X, Z> z;
|
|
||||||
|
|
||||||
** if the collection type of z is java.util.Set, then
|
|
||||||
|
|
||||||
public static volatile SetAttribute<X, Z> z;
|
|
||||||
|
|
||||||
** if the collection type of z is java.util.List, then
|
|
||||||
|
|
||||||
public static volatile ListAttribute<X, Z> z;
|
|
||||||
|
|
||||||
** if the collection type of z is java.util.Map, then
|
|
||||||
+
|
|
||||||
public static volatile MapAttribute<X, K, Z> z;
|
|
||||||
+
|
|
||||||
where K is the type of the key of the map in class X
|
|
||||||
|
|
||||||
Import statements must be included for the needed `jakarta.persistence.metamodel` types as
|
|
||||||
appropriate and all classes X, Y, Z, and K.
|
|
||||||
|
|
||||||
[[chapter-usage]]
|
|
||||||
== Usage
|
|
||||||
|
|
||||||
The jar file for the annotation processor can be found in the
|
|
||||||
https://search.maven.org/[Maven Central repository] under:
|
|
||||||
|
|
||||||
====
|
|
||||||
[source, XML]
|
|
||||||
[subs="verbatim,attributes"]
|
|
||||||
----
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.hibernate</groupId>
|
|
||||||
<artifactId>hibernate-jpamodelgen</artifactId>
|
|
||||||
<version>{version}</version>
|
|
||||||
</dependency>
|
|
||||||
----
|
|
||||||
====
|
|
||||||
|
|
||||||
Alternatively, it can be found in the ORM distribution bundle on
|
|
||||||
https://sourceforge.net/projects/hibernate/files/hibernate-orm/[SourceForge].
|
|
||||||
|
|
||||||
In most cases the annotation processor will automatically run provided
|
|
||||||
the processor jar is added to the build classpath.
|
|
||||||
This happens due to Java's Service Provider contract and the fact
|
|
||||||
the Hibernate Static Metamodel Generator jar files contains the
|
|
||||||
file _javax.annotation.processing.Processor_ in the _META-INF/services_ directory.
|
|
||||||
|
|
||||||
The fully qualified name of the processor itself is:
|
|
||||||
`org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor`.
|
|
||||||
|
|
||||||
=== Usage from the command line
|
|
||||||
|
|
||||||
[[usage-ant]]
|
|
||||||
==== Usage with Ant
|
|
||||||
|
|
||||||
As mentioned above, the annotation processor will run automatically
|
|
||||||
each time the Java compiler is called, provided the jar file is on the
|
|
||||||
classpath.
|
|
||||||
Sometimes, however, it is useful to control the annotation
|
|
||||||
processing in more detail, for example if you exclusively want to run
|
|
||||||
the processor without compiling any other source files.
|
|
||||||
The <<javac-task-example,Javac task>> configuration below shows how
|
|
||||||
Ant can be configured to just run annotation processing.
|
|
||||||
|
|
||||||
[[javac-task-example]]
|
|
||||||
.Javac Task configuration
|
|
||||||
====
|
|
||||||
[source, XML]
|
|
||||||
----
|
|
||||||
<javac srcdir="${src.dir}"
|
|
||||||
destdir="${target.dir}"
|
|
||||||
failonerror="false"
|
|
||||||
fork="true"
|
|
||||||
classpath="${classpath}">
|
|
||||||
<compilerarg value="-proc:only"/>
|
|
||||||
</javac>
|
|
||||||
----
|
|
||||||
|
|
||||||
====
|
|
||||||
The option _-proc:only_ instructs the compiler to just run the annotation processing.
|
|
||||||
You can also completely disable processing by specifying _-proc:none_.
|
|
||||||
|
|
||||||
[TIP]
|
|
||||||
====
|
|
||||||
Run `'javac -help'` to see which other annotation processor relevant
|
|
||||||
options can be specified.
|
|
||||||
====
|
|
||||||
|
|
||||||
==== Usage with Maven
|
|
||||||
|
|
||||||
There are several ways of running the annotation processor as part of a Maven build.
|
|
||||||
Again, it will automatically run if you are compiling with a JDK >6.
|
|
||||||
In case you have more than one annotation processor on your classpath you can explicitly
|
|
||||||
pass the processor option to the compiler plugin:
|
|
||||||
|
|
||||||
.Maven compiler plugin configuration - direct execution
|
|
||||||
|
|
||||||
====
|
|
||||||
[source, XML]
|
|
||||||
----
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
|
||||||
<configuration>
|
|
||||||
<source>1.8</source>
|
|
||||||
<target>1.8</target>
|
|
||||||
<compilerArguments>
|
|
||||||
<processor>org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor</processor>
|
|
||||||
</compilerArguments>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
----
|
|
||||||
|
|
||||||
====
|
|
||||||
The maven-compiler-plugin approach has the disadvantage that the maven compiler plugin
|
|
||||||
does currently not allow to specify multiple compiler arguments
|
|
||||||
(https://jira.codehaus.org/browse/MCOMPILER-62[MCOMPILER-62])
|
|
||||||
and that messages from the Messenger API are suppressed
|
|
||||||
(https://jira.codehaus.org/browse/MCOMPILER-66[MCOMPILER-66]).
|
|
||||||
A better approach is to disable annotation processing for the compiler
|
|
||||||
plugin as seen in below.
|
|
||||||
|
|
||||||
[[disable-processing-maven-compiler-plugin]]
|
|
||||||
.Maven compiler plugin configuration - indirect execution
|
|
||||||
|
|
||||||
====
|
|
||||||
[source, XML]
|
|
||||||
----
|
|
||||||
<plugin>
|
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
|
||||||
<configuration>
|
|
||||||
<source>1.8</source>
|
|
||||||
<target>1.8</target>
|
|
||||||
<compilerArgument>-proc:none</compilerArgument>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
----
|
|
||||||
====
|
|
||||||
Once disabled, the https://bsorrentino.github.io/maven-annotation-plugin/[maven-processor-plugin]
|
|
||||||
for annotation processing can be used:
|
|
||||||
|
|
||||||
[[maven-processor-plugin]]
|
|
||||||
.Configuration with maven-processor-plugin
|
|
||||||
====
|
|
||||||
[source, XML]
|
|
||||||
[subs="verbatim,attributes"]
|
|
||||||
----
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.bsc.maven</groupId>
|
|
||||||
<artifactId>maven-processor-plugin</artifactId>
|
|
||||||
<version>2.0.5</version>
|
|
||||||
<executions>
|
|
||||||
<execution>
|
|
||||||
<id>process</id>
|
|
||||||
<goals>
|
|
||||||
<goal>process</goal>
|
|
||||||
</goals>
|
|
||||||
<phase>generate-sources</phase>
|
|
||||||
<configuration>
|
|
||||||
<processors>
|
|
||||||
<processor>org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor</processor>
|
|
||||||
</processors>
|
|
||||||
</configuration>
|
|
||||||
</execution>
|
|
||||||
</executions>
|
|
||||||
<dependencies>
|
|
||||||
<dependency>
|
|
||||||
<groupId>org.hibernate</groupId>
|
|
||||||
<artifactId>hibernate-jpamodelgen</artifactId>
|
|
||||||
<version>{version}</version>
|
|
||||||
</dependency>
|
|
||||||
</dependencies>
|
|
||||||
</plugin>
|
|
||||||
----
|
|
||||||
====
|
|
||||||
|
|
||||||
Another possibility is to supply the dependency as an annotation processor path to the maven-compiler-plugin:
|
|
||||||
|
|
||||||
[[maven-compiler-plugin]]
|
|
||||||
.Configuration with maven-compiler-plugin
|
|
||||||
====
|
|
||||||
[source, XML]
|
|
||||||
[subs="verbatim,attributes"]
|
|
||||||
----
|
|
||||||
<plugin>
|
|
||||||
<groupId>org.apache.maven.plugins</groupId>
|
|
||||||
<artifactId>maven-compiler-plugin</artifactId>
|
|
||||||
<version>3.7.0</version>
|
|
||||||
<configuration>
|
|
||||||
<annotationProcessorPaths>
|
|
||||||
<path>
|
|
||||||
<groupId>org.hibernate</groupId>
|
|
||||||
<artifactId>hibernate-jpamodelgen</artifactId>
|
|
||||||
<version>{fullVersion}</version>
|
|
||||||
</path>
|
|
||||||
</annotationProcessorPaths>
|
|
||||||
</configuration>
|
|
||||||
</plugin>
|
|
||||||
----
|
|
||||||
====
|
|
||||||
|
|
||||||
=== Usage within the IDE
|
|
||||||
|
|
||||||
Of course you also want to have annotation processing available in your favorite IDE. The
|
|
||||||
following paragraphs and screenshots show you how to enable the Hibernate Static Metamodel
|
|
||||||
Generator within your IDE.
|
|
||||||
|
|
||||||
==== Idea
|
|
||||||
|
|
||||||
Intellij Idea contains from version 9.x onwards a specific configuration section for
|
|
||||||
annotation processing under the project settings window.
|
|
||||||
The screenshots show you how to configure the Hibernate Static Metamodel Generator.
|
|
||||||
|
|
||||||
image:idea-annotation-processor-config.png[]
|
|
||||||
|
|
||||||
In the annotation processor configuration, enable annotation processing and select obtain
|
|
||||||
from project classpath.
|
|
||||||
Add the annotation processor name `org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor`
|
|
||||||
(and optionally the annotation processor options).
|
|
||||||
Select the module(s) containing your entities.
|
|
||||||
If you have configured Maven as recommended, it is best to select the same output directory
|
|
||||||
for the generated classes.
|
|
||||||
At the time of writing, it is _target/generated-sources/apt_. That way, the generated
|
|
||||||
classes will be available in IntelliJ Idea.
|
|
||||||
|
|
||||||
==== Eclipse
|
|
||||||
|
|
||||||
In Eclipse exists also an additional configuration section under Java Compiler.
|
|
||||||
There you can configure all kinds of aspects of annotation processing.
|
|
||||||
Just check the "Enable annotation processing" option, configure the directory for the
|
|
||||||
generated sources and finally add the Hibernate Static Metamodel Generator and Jakarta Persistence jar
|
|
||||||
files to the factory path.
|
|
||||||
|
|
||||||
image:eclipse-annotation-processor-config.png[]
|
|
||||||
|
|
||||||
=== Processor specific options
|
|
||||||
|
|
||||||
The Hibernate Static Metamodel Generator accepts a series of custom
|
|
||||||
options which can be passed to the processor in the format: `-A[property]=[value]`
|
|
||||||
|
|
||||||
The supported properties can be found in the table below:
|
|
||||||
|
|
||||||
.Hibernate Static Metamodel Generator options
|
|
||||||
|===============
|
|
||||||
|*Option name* | *Option value and usage*
|
|
||||||
|
|
||||||
|debug | If set to `true` additional trace
|
|
||||||
information will be outputted by the processor
|
|
||||||
|
|
||||||
|persistenceXml | Per default the processor looks in
|
|
||||||
_/META-INF_ for persistence.xml. Specifying
|
|
||||||
this option a _persitence.xml_ file from a
|
|
||||||
different location can be specified
|
|
||||||
(has to be on the classpath)
|
|
||||||
|
|
||||||
|ormXml | Allows to specify additional entity mapping
|
|
||||||
files. The specified value for this option is a
|
|
||||||
comma separated string of mapping file names.
|
|
||||||
Even when this option is specified
|
|
||||||
_/META-INF/orm.xml_ is implicit.
|
|
||||||
|
|
||||||
|lazyXmlParsing | Possible values are `true` or `false`. If set to
|
|
||||||
`true` the annotation processor tries to
|
|
||||||
determine whether any of the xml files has
|
|
||||||
changed between
|
|
||||||
invocations and if unchanged skips the xml parsing.
|
|
||||||
This feature is experimental and contains the risk
|
|
||||||
of wrong results in some cases of mixed mode
|
|
||||||
configurations. To determine wether a file has
|
|
||||||
been modified a temporary file
|
|
||||||
`Hibernate-Static-Metamodel-Generator.tmp`
|
|
||||||
is used. This file gets created in the
|
|
||||||
`java.io.tmpdir` directory.
|
|
||||||
|
|
||||||
|fullyAnnotationConfigured | If set to `true` the processor will
|
|
||||||
ignore `orm.xml` and `persistence.xml`.
|
|
||||||
|
|
||||||
|addGeneratedAnnotation | If set to `true` the processor will
|
|
||||||
add the @Generated to the generated
|
|
||||||
Java source file. Adding this annotation using
|
|
||||||
JDK 5 will cause a compilation error. In this
|
|
||||||
case set the flag to false. The default for this option is `true`
|
|
||||||
|
|
||||||
|addGenerationDate | If set to true the generation date
|
|
||||||
of the metamodel class will be inserted in the
|
|
||||||
date parameter of the @Generated annotation.
|
|
||||||
The default is `false`. This parameter is
|
|
||||||
ignored if _addGeneratedAnnotation_ is set
|
|
||||||
to _false_.
|
|
||||||
|addSuppressWarningsAnnotation| If set to `true` the processor will
|
|
||||||
add `@SuppressWarnings("all")` to the
|
|
||||||
generated Java source file. Per default this
|
|
||||||
annotation is not generated. See also https://hibernate.onjira.com/browse/METAGEN-50[METAGEN-50].
|
|
||||||
|
|
||||||
|===============
|
|
||||||
|
|
||||||
|
|
|
@ -1,132 +0,0 @@
|
||||||
[[custom-sf-session-guide]]
|
|
||||||
= Custom SessionFactory and Session Implementations Guide
|
|
||||||
:toc:
|
|
||||||
|
|
||||||
The two main contracts of Hibernate, `org.hibernate.SessionFactory` and `org.hibernate.Session`, are both
|
|
||||||
defined as interfaces which allows for custom implementations to be provided. There are two high-level ways
|
|
||||||
in which custom implementations can be provided to users. The first is to develop a custom bootstrap API
|
|
||||||
specific to the custom implementation. The second way is to integrate with the Hibernate bootstrap API.
|
|
||||||
This guide will cover the second approach.
|
|
||||||
|
|
||||||
|
|
||||||
== Implementor contracts
|
|
||||||
|
|
||||||
A Hibernate naming convention is that SPI contracts extending API contracts are named with Implementor appended
|
|
||||||
to the API contract name. For `SessionFactory` and `Session` that is `SessionFactoryImplementor` and
|
|
||||||
`SessionImplementor` respectively. These SPI contracts extra information and functionality needed by internal
|
|
||||||
components as well as other SPI components. Therefore, custom `SessionFactory` and `Session` should additionally
|
|
||||||
implement `org.hibernate.engine.spi.SessionFactoryImplementor` and `org.hibernate.engine.spi.SessionImplementor`.
|
|
||||||
See all pertinent JavaDocs for discussions of implementation details.
|
|
||||||
|
|
||||||
|
|
||||||
== Integration hooks
|
|
||||||
|
|
||||||
`org.hibernate.boot.SessionFactoryBuilder` is part of the Hibernate native bootstrap API where we want to configure
|
|
||||||
the `SessionFactory` to be built. Third parties can hook into this process by supplying a
|
|
||||||
`org.hibernate.boot.spi.SessionFactoryBuilderFactory` via the Java ServiceLoader mechanism (see JavaDocs for
|
|
||||||
`java.util.ServiceLoader` if you are unfamiliar with this service discovery mechanism). As you might guess from their
|
|
||||||
names, a `SessionFactoryBuilderFactory` is responsible for creating `SessionFactoryBuilder` instances and a
|
|
||||||
`SessionFactoryBuilder` is in turn responsible for creating `SessionFactory` instances.
|
|
||||||
|
|
||||||
`org.hibernate.boot.spi.SessionFactoryOptions` are the options ultimately passed to the `SessionFactory` being
|
|
||||||
built. They represent the choices applied by the user via the `SessionFactoryBuilder` contract. Custom integrations
|
|
||||||
can leverage this and the `SessionFactoryBuilder` to also expose custom option setting.
|
|
||||||
|
|
||||||
|
|
||||||
[[example1]]
|
|
||||||
.Custom SessionFactoryBuilderFactory with additional option
|
|
||||||
====
|
|
||||||
[source, JAVA]
|
|
||||||
----
|
|
||||||
public class CustomSessionFactoryBuilderFactory
|
|
||||||
implements SessionFactoryBuilderFactory {
|
|
||||||
@Override
|
|
||||||
public SessionFactoryBuilder getSessionFactoryBuilder(
|
|
||||||
MetadataImplementor metadata,
|
|
||||||
SessionFactoryBuilderImplementor defaultBuilder) {
|
|
||||||
return new CustomSessionFactoryBuilder( metadata, defaultBuilder );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class CustomSessionFactoryBuilder
|
|
||||||
extends AbstractDelegatingSessionFactoryBuilder {
|
|
||||||
private final MetadataImplementor metadata;
|
|
||||||
|
|
||||||
private final boolean customSetting;
|
|
||||||
|
|
||||||
public DelegatingSessionFactoryBuilder(
|
|
||||||
MetadataImplementor metadata,
|
|
||||||
SessionFactoryBuilderImplementor delegate) {
|
|
||||||
super( delegate );
|
|
||||||
this.metadata = metadata;
|
|
||||||
|
|
||||||
// initialize customSetting, maybe based on config settings...
|
|
||||||
ConfigurationService cfgService = metadata.getMetadataBuildingOptions()
|
|
||||||
.getServiceRegistry()
|
|
||||||
.getService( ConfigurationService.class );
|
|
||||||
this.customSetting = cfgService.getSetting(
|
|
||||||
"com.acme.domain.custom_setting",
|
|
||||||
StandardConverters.BOOLEAN,
|
|
||||||
true
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public DelegatingSessionFactoryBuilder unwrap() {
|
|
||||||
return (DelegatingSessionFactoryBuilder) this;
|
|
||||||
}
|
|
||||||
|
|
||||||
public CustomSessionFactoryBuilder applyCustomSetting(boolean enabled) {
|
|
||||||
this.customSetting = enabled;
|
|
||||||
return this;
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public SessionFactory build() {
|
|
||||||
CustomSessionFactoryOptions options = new CustomSessionFactoryOptions(
|
|
||||||
getDelegate().buildSessionFactoryOptions(),
|
|
||||||
customSetting
|
|
||||||
);
|
|
||||||
return new CustomSessionFactory( metadata, options );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public class CustomSessionFactoryOptions
|
|
||||||
extends AbstractDelegatingSessionFactoryOptions {
|
|
||||||
private final boolean customSetting;
|
|
||||||
|
|
||||||
public CustomSessionFactoryOptions(
|
|
||||||
SessionFactoryOptions baseOptions,
|
|
||||||
boolean customSetting) {
|
|
||||||
super( baseOptions );
|
|
||||||
this.customSetting = customSetting;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean getCustomSetting() {
|
|
||||||
return customSetting;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
----
|
|
||||||
====
|
|
||||||
|
|
||||||
Users can then build your custom `SessionFactory` still using the normal Hibernate bootstrap. In fact,
|
|
||||||
accepting defaults for your custom settings/options, their code does not even change. Of course they
|
|
||||||
can also apply selections to your custom settings/options as well:
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[[example2]]
|
|
||||||
.Example usage
|
|
||||||
====
|
|
||||||
[source, JAVA]
|
|
||||||
----
|
|
||||||
Metadata metadata = ...;
|
|
||||||
|
|
||||||
// The SessionFactory returned here is concretely
|
|
||||||
// a CustomSessionFactory
|
|
||||||
SessionFactory sf = metadata.getSessionFactoryBuilder()
|
|
||||||
.unwrap( CustomSessionFactoryBuilder.class )
|
|
||||||
.applyCustomSetting( false )
|
|
||||||
.buildSessionFactory();
|
|
||||||
----
|
|
||||||
====
|
|
|
@ -1,18 +0,0 @@
|
||||||
[[wildfly-guide]]
|
|
||||||
= Using latest Hibernate ORM within WildFly
|
|
||||||
|
|
||||||
== Hibernate ORM within WildFly
|
|
||||||
|
|
||||||
The https://wildfly.org/[WildFly application server] includes Hibernate ORM as the default Jakarta Persistence provider out of the box.
|
|
||||||
|
|
||||||
In previous versions of Hibernate ORM, we offered a "feature pack" to enable anyone to use the very latest version in
|
|
||||||
WildFly as soon as a new release of Hibernate ORM was published.
|
|
||||||
|
|
||||||
Unfortunately, since version 5.5 is upgrading to Jakarta Persistence 3.0 and targets integration with components of the Jakarta
|
|
||||||
EE 9 stack, such feature had to be disabled.
|
|
||||||
|
|
||||||
As soon as WildFly releases a Jakarta EE 9 compatible server it might be possible to re-introduce such a feature, but
|
|
||||||
we can't guarantee that we will do this as the server changed the tooling to define such packs.
|
|
||||||
|
|
||||||
As usual, please let us know how important this is for you, and while we'll gladly help to make this happen we might need
|
|
||||||
to rely on volunteers to help by contributing patches, testing it out and providing feedback.
|
|
|
@ -62,7 +62,8 @@ It was done here only for completeness of an example.
|
||||||
|
|
||||||
The `Person_.name` reference is an example of the static form of Jakarta Persistence Metamodel reference.
|
The `Person_.name` reference is an example of the static form of Jakarta Persistence Metamodel reference.
|
||||||
We will use that form exclusively in this chapter.
|
We will use that form exclusively in this chapter.
|
||||||
See the documentation for the https://docs.jboss.org/hibernate/orm/{majorMinorVersion}/topical/html_single/metamodelgen/MetamodelGenerator.html[Hibernate Jakarta Persistence Metamodel Generator] for additional details on the Jakarta Persistence static Metamodel.
|
|
||||||
|
See <<tooling>> for details on generating this static metamodel.
|
||||||
====
|
====
|
||||||
|
|
||||||
[[criteria-typedquery-expression]]
|
[[criteria-typedquery-expression]]
|
||||||
|
|
|
@ -1,90 +1,25 @@
|
||||||
[[tooling]]
|
[[tooling]]
|
||||||
== Build Tool Integration
|
== Build Tool Integration
|
||||||
|
:rootProjectDir: ../../../../../../..
|
||||||
|
:documentationProjectDir: {rootProjectDir}/documentation
|
||||||
|
:documentationModel: {documentationProjectDir}/src/main/java/org/hibernate/userguide/model
|
||||||
|
|
||||||
Hibernate provides a few build-time services available as plugins for
|
Hibernate provides build-time services available as plugins for
|
||||||
https://gradle.org[Gradle], https://maven.org[Maven] and https://ant.org[Ant].
|
|
||||||
|
|
||||||
These services include -
|
* <<tooling-gradle,Gradle>>
|
||||||
|
* <<tooling-maven,Maven>>
|
||||||
|
* <<tooling-ant,Ant>>
|
||||||
|
|
||||||
* Bytecode enhancement
|
These services include
|
||||||
* Schema management
|
|
||||||
* Static Metamodel generation
|
|
||||||
|
|
||||||
|
* <<tooling-enhancement,Bytecode enhancement>>
|
||||||
|
* <<tooling-modelgen,Static Metamodel generation>>
|
||||||
|
* <<tooling-schema,Schema management>>
|
||||||
|
|
||||||
[[tooling-enhancement]]
|
include::enhancement.adoc[]
|
||||||
=== Bytecode Enhancement
|
include::modelgen.adoc[]
|
||||||
|
include::schema.adoc[]
|
||||||
|
|
||||||
Hibernate performs bytecode enhancement through its `org.hibernate.bytecode.enhance.spi.Enhancer`
|
include::gradle.adoc[]
|
||||||
contract. These build time tools provide a way to incorporate configuration and execution of
|
include::maven.adoc[]
|
||||||
the enhancer into a build.
|
include::ant.adoc[]
|
||||||
|
|
||||||
See <<BytecodeEnhancement>> for discussion of the capabilities of an enhanced model.
|
|
||||||
|
|
||||||
[NOTE]
|
|
||||||
====
|
|
||||||
At the moment, only annotated classes are supported for enhancement.
|
|
||||||
====
|
|
||||||
|
|
||||||
|
|
||||||
[[tooling-enhancement-runtime]]
|
|
||||||
==== Runtime Bytecode Enhancement
|
|
||||||
|
|
||||||
Hibernate can also perform run-time bytecode enhancement when used in Jakarta EE compliant
|
|
||||||
containers through `jakarta.persistence.spi.ClassTransformer`. See the documentation of
|
|
||||||
your container for any additional details. Run-time enhancement is controlled through
|
|
||||||
3 true/false settings (all of which default to false):
|
|
||||||
|
|
||||||
`hibernate.enhancer.enableDirtyTracking`:: Whether to enhance the model for dirty-tracking
|
|
||||||
`hibernate.enhancer.enableLazyInitialization`:: Whether to enhance the model for lazy loading at the attribute level. This allows
|
|
||||||
even basic types to be fetched lazily. It also allows definition of fetch groups (`LazyGroup`).
|
|
||||||
`hibernate.enhancer.enableAssociationManagement`:: Whether to automatically synchronize a bidirectional association when only one side is changed.
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[[tooling-schema]]
|
|
||||||
=== Schema Management
|
|
||||||
|
|
||||||
|
|
||||||
[[tooling-modelgen]]
|
|
||||||
=== Static Metamodel Generation
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
[[tooling-gradle]]
|
|
||||||
=== Gradle Plugin
|
|
||||||
|
|
||||||
For integrating with Gradle, Hibernate provides the
|
|
||||||
https://plugins.gradle.org/plugin/org.hibernate.orm[org.hibernate.orm] plugin which
|
|
||||||
supports bytecode enhancement and static metamodel generation but not schema tooling.
|
|
||||||
|
|
||||||
[source,gradle]
|
|
||||||
----
|
|
||||||
include::extras/gradle-example.gradle[]
|
|
||||||
----
|
|
||||||
|
|
||||||
|
|
||||||
[[tooling-maven]]
|
|
||||||
=== Maven Plugin
|
|
||||||
|
|
||||||
Hibernate provides a Maven plugin capable of providing build-time enhancement of the domain
|
|
||||||
model as they are compiled as part of a Maven build. See the section on the
|
|
||||||
<<BytecodeEnhancement-enhancement-gradle>> for details on the configuration settings. Again, the default for those 3 is `false`.
|
|
||||||
|
|
||||||
The Maven plugin supports one additional configuration settings: failOnError, which controls what happens in case of error.
|
|
||||||
The default behavior is to fail the build, but it can be set so that only a warning is issued.
|
|
||||||
|
|
||||||
.Apply the Maven plugin
|
|
||||||
====
|
|
||||||
[source,xml]
|
|
||||||
----
|
|
||||||
include::extras/maven-example.pom[]
|
|
||||||
----
|
|
||||||
====
|
|
||||||
|
|
||||||
|
|
||||||
[[tooling-ant]]
|
|
||||||
=== Ant Plugin
|
|
||||||
|
|
||||||
todo - https://hibernate.atlassian.net/browse/HHH-15171
|
|
||||||
|
|
|
@ -0,0 +1,36 @@
|
||||||
|
[[tooling-ant]]
|
||||||
|
=== Ant Plugin
|
||||||
|
|
||||||
|
Hibernate provides https://ant.apache.org/[Ant] support ...
|
||||||
|
|
||||||
|
|
||||||
|
[[tooling-ant-modelgen]]
|
||||||
|
==== Static Metamodel Generation in Ant
|
||||||
|
|
||||||
|
As mentioned in <<tooling-modelgen>>, the generator is implemented as an
|
||||||
|
annotation processor and can be used anywhere javac is used - such as
|
||||||
|
Ant's https://ant.apache.org/manual/Tasks/javac.html[javac] task.
|
||||||
|
|
||||||
|
[[javac-task-example]]
|
||||||
|
.Javac task configuration
|
||||||
|
====
|
||||||
|
[source, XML]
|
||||||
|
----
|
||||||
|
<javac srcdir="${src.dir}"
|
||||||
|
destdir="${target.dir}"
|
||||||
|
failonerror="false"
|
||||||
|
fork="true"
|
||||||
|
classpath="${classpath}">
|
||||||
|
<compilerarg value="-processorpath" />
|
||||||
|
<compilerarg value="/path/to/metamodel-generator.jar"/>
|
||||||
|
<compilerarg value="-proc:only"/>
|
||||||
|
</javac>
|
||||||
|
----
|
||||||
|
|
||||||
|
====
|
||||||
|
|
||||||
|
|
||||||
|
[[tooling-ant-schema]]
|
||||||
|
==== Schema Management
|
||||||
|
|
||||||
|
Coming soon
|
|
@ -0,0 +1,27 @@
|
||||||
|
[[tooling-enhancement]]
|
||||||
|
=== Bytecode Enhancement
|
||||||
|
|
||||||
|
Hibernate performs bytecode enhancement through its `org.hibernate.bytecode.enhance.spi.Enhancer`
|
||||||
|
contract. These build time tools provide a way to incorporate configuration and execution of
|
||||||
|
the enhancer into a build.
|
||||||
|
|
||||||
|
See <<BytecodeEnhancement>> for discussion of the capabilities of an enhanced model.
|
||||||
|
|
||||||
|
[NOTE]
|
||||||
|
====
|
||||||
|
At the moment, only annotated classes are supported for enhancement.
|
||||||
|
====
|
||||||
|
|
||||||
|
|
||||||
|
[[tooling-enhancement-runtime]]
|
||||||
|
==== Runtime Bytecode Enhancement
|
||||||
|
|
||||||
|
Hibernate can also perform run-time bytecode enhancement when used in Jakarta EE compliant
|
||||||
|
containers through `jakarta.persistence.spi.ClassTransformer`. See the documentation of
|
||||||
|
your container for any additional details. Run-time enhancement is controlled through
|
||||||
|
3 true/false settings (all of which default to false):
|
||||||
|
|
||||||
|
`hibernate.enhancer.enableDirtyTracking`:: Whether to enhance the model for dirty-tracking
|
||||||
|
`hibernate.enhancer.enableLazyInitialization`:: Whether to enhance the model for lazy loading at the attribute level. This allows
|
||||||
|
even basic types to be fetched lazily. It also allows definition of fetch groups (`LazyGroup`).
|
||||||
|
`hibernate.enhancer.enableAssociationManagement`:: Whether to automatically synchronize a bidirectional association when only one side is changed.
|
|
@ -1,23 +0,0 @@
|
||||||
plugins {
|
|
||||||
// e.g., let's use the 6.0.0.Final version of the plugin
|
|
||||||
id "org.hibernate.orm" version "6.0.0.Final"
|
|
||||||
}
|
|
||||||
|
|
||||||
hibernate {
|
|
||||||
enhancement {
|
|
||||||
// all default to false
|
|
||||||
lazyInitialization true
|
|
||||||
dirtyTracking true
|
|
||||||
associationManagement true
|
|
||||||
}
|
|
||||||
jpaMetamodel {
|
|
||||||
// defaults to true
|
|
||||||
applyGeneratedAnnotation true
|
|
||||||
// defaults to ['raw', 'deprecation']
|
|
||||||
suppress 'raw'
|
|
||||||
// defaults to `${buildDir}/generated/sources/jpaMetamodel
|
|
||||||
generationOutputDirectory "${buildDir}/generated/sources/modelgen"
|
|
||||||
// defaults to `${buildDir}/classes/java/jpaMetamodel
|
|
||||||
compileOutputDirectory "${buildDir}/classes/java/modelgen"
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,113 @@
|
||||||
|
[[tooling-gradle]]
|
||||||
|
=== Gradle Plugin
|
||||||
|
|
||||||
|
For integrating with https://gradle.org[Gradle], Hibernate provides the
|
||||||
|
https://plugins.gradle.org/plugin/org.hibernate.orm[org.hibernate.orm] plugin which
|
||||||
|
supports bytecode enhancement and static metamodel generation but not schema tooling.
|
||||||
|
|
||||||
|
To apply the plugin, use Gradle's `plugins {}` block:
|
||||||
|
|
||||||
|
[source,gradle]
|
||||||
|
----
|
||||||
|
plugins {
|
||||||
|
id "org.hibernate.orm" version "<version-to-use>"
|
||||||
|
}
|
||||||
|
----
|
||||||
|
|
||||||
|
|
||||||
|
Applying the plugin creates a `hibernate` extension (`HibernateOrmSpec`) to configure the plugin.
|
||||||
|
By default, when the plugin is applied, support for both bytecode enhancement and static metamodel
|
||||||
|
generation is enabled.
|
||||||
|
|
||||||
|
[source,gradle]
|
||||||
|
----
|
||||||
|
hibernate {
|
||||||
|
// for illustration, let's disable both
|
||||||
|
disableEnhancement
|
||||||
|
disableJpaMetamodel
|
||||||
|
}
|
||||||
|
----
|
||||||
|
|
||||||
|
[[tooling-gradle-enhancement]]
|
||||||
|
==== Bytecode Enhancement
|
||||||
|
|
||||||
|
Enhancement is configured through the `enhancement` extension:
|
||||||
|
|
||||||
|
[source,gradle]
|
||||||
|
----
|
||||||
|
hibernate {
|
||||||
|
enhancement {
|
||||||
|
// for illustration, enable them all
|
||||||
|
lazyInitialization true
|
||||||
|
dirtyTracking true
|
||||||
|
associationManagement true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
----
|
||||||
|
|
||||||
|
The extension is of type `EnhancementSpec` which exposes the following properties:
|
||||||
|
|
||||||
|
|
||||||
|
enableLazyInitialization:: Whether to incorporate lazy loading support into the enhanced bytecode
|
||||||
|
enableDirtyTracking:: Whether to incorporate dirty tracking into the enhanced bytecode
|
||||||
|
enableAssociationManagement:: Whether to add bidirectional association management into the enhanced bytecode
|
||||||
|
|
||||||
|
|
||||||
|
Which all default to false (disabled).
|
||||||
|
|
||||||
|
It also exposes the following method forms:
|
||||||
|
|
||||||
|
* lazyInitialization(boolean)
|
||||||
|
* dirtyTracking(boolean)
|
||||||
|
* associationManagement(boolean)
|
||||||
|
|
||||||
|
|
||||||
|
[[tooling-gradle-modelgen]]
|
||||||
|
==== Static Metamodel Generation
|
||||||
|
|
||||||
|
One approach to integrate Static Metamodel generation into a Gradle build is to
|
||||||
|
use Gradle's support for annotation processors -
|
||||||
|
|
||||||
|
[source,gradle]
|
||||||
|
----
|
||||||
|
dependencies {
|
||||||
|
annotationProcessor "org.hibernate.orm:hibernate-jpamodelgen:${hibernateVersion}"
|
||||||
|
}
|
||||||
|
----
|
||||||
|
|
||||||
|
When the build does not need bytecode enhancement support, this is a perfectly valid solution.
|
||||||
|
|
||||||
|
The plugin supports simpler configuration of the generator using the registered
|
||||||
|
`jpaMetamodel` extension:
|
||||||
|
|
||||||
|
|
||||||
|
[source,gradle]
|
||||||
|
----
|
||||||
|
hibernate {
|
||||||
|
jpaMetamodel {
|
||||||
|
applyGeneratedAnnotation false
|
||||||
|
suppress 'raw'
|
||||||
|
generationOutputDirectory "${buildDir}/generated/sources/modelgen"
|
||||||
|
compileOutputDirectory "${buildDir}/classes/java/modelgen"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
----
|
||||||
|
|
||||||
|
The extension is of type `JpaMetamodelGenerationSpec`, which exposes the following configuration properties:
|
||||||
|
|
||||||
|
applyGeneratedAnnotation:: Should the `javax.annotation.processing.Generated` annotation be added to the
|
||||||
|
generated classes. Defaults to `true`.
|
||||||
|
suppressions:: Suppressions to add to the generated classes. Defaults to `['raw', 'deprecation']`
|
||||||
|
generationOutputDirectory:: Directory where the generated metamodel classes should be created. Defaults
|
||||||
|
to `${buildDir}/generated/sources/jpaMetamodel`
|
||||||
|
[[tooling-gradle-modelgen-compile-output]]
|
||||||
|
compileOutputDirectory:: Directory where the classes compiled from the generated metamodel classes should be
|
||||||
|
created. Defaults to `${buildDir}/classes/java/jpaMetamodel`.
|
||||||
|
|
||||||
|
It also exposes the following method forms:
|
||||||
|
|
||||||
|
* applyGeneratedAnnotation(boolean)
|
||||||
|
* suppress(String)
|
||||||
|
* generationOutputDirectory(Object)
|
||||||
|
* compileOutputDirectory(Object)
|
||||||
|
|
Before Width: | Height: | Size: 173 KiB After Width: | Height: | Size: 173 KiB |
Before Width: | Height: | Size: 365 KiB After Width: | Height: | Size: 365 KiB |
|
@ -0,0 +1,16 @@
|
||||||
|
[[tooling-maven]]
|
||||||
|
=== Maven Plugin
|
||||||
|
|
||||||
|
Hibernate provides a https://maven.apache.org/[Maven] plugin capable of providing
|
||||||
|
build-time enhancement of the domain model as they are compiled as part of a Maven
|
||||||
|
build. See the section on the <<tooling-gradle>> for details
|
||||||
|
on the configuration settings. By default, all enhancements are disabled.
|
||||||
|
|
||||||
|
|
||||||
|
.Apply the Maven plugin
|
||||||
|
====
|
||||||
|
[source,xml]
|
||||||
|
----
|
||||||
|
include::extras/maven-example.pom[]
|
||||||
|
----
|
||||||
|
====
|
|
@ -0,0 +1,109 @@
|
||||||
|
[[tooling-modelgen]]
|
||||||
|
=== Static Metamodel Generator
|
||||||
|
:rootProjectDir: ../../../../../../..
|
||||||
|
:documentationProjectDir: {rootProjectDir}/documentation
|
||||||
|
:documentationModel: {documentationProjectDir}/src/main/java/org/hibernate/userguide/model
|
||||||
|
:documentationMetamodel: {documentationProjectDir}/target/generated/sources/annotationProcessor/java/main/org/hibernate/userguide/model
|
||||||
|
:toolingTestsDir: {documentationProjectDir}/src/test/java/org/hibernate/userguide/tooling
|
||||||
|
|
||||||
|
Jakarta Persistence defines a typesafe Criteria API which allows `Criteria` queries to be constructed in a
|
||||||
|
strongly-typed manner, utilizing so-called static metamodel classes. For developers, it is important that
|
||||||
|
the task of the metamodel generation can be automated. Hibernate Static Metamodel Generator is an annotation
|
||||||
|
processor based on https://jcp.org/en/jsr/detail?id=269[JSR_269] with the task of creating Jakarta Persistence
|
||||||
|
static metamodel classes.
|
||||||
|
|
||||||
|
See <<criteria>> for discussion of Jakarta Persistence criteria queries.
|
||||||
|
|
||||||
|
The Hibernate Static Metamodel Generator is defined by the published `org.hibernate.orm:metamodel-generator`
|
||||||
|
artifact. As it is defined as an
|
||||||
|
https://docs.oracle.com/en/java/javase/11/tools/javac.html#GUID-082C33A5-CBCA-471A-845E-E77F79B7B049[annotation processor],
|
||||||
|
it is usable anytime `javac` is used. See the tool-specific discussions (<<tooling-gradle,Gradle>>, <<tooling-maven,Maven>>
|
||||||
|
and <<tooling-ant,Ant>>) for details on integrating the generator into those environments.
|
||||||
|
|
||||||
|
NOTE:: The fully qualified name of the processor class is `org.hibernate.jpamodelgen.JPAMetaModelEntityProcessor`.
|
||||||
|
|
||||||
|
[TIP]
|
||||||
|
====
|
||||||
|
The `javac` option _-proc:only_ instructs the compiler to just run the annotation processing.
|
||||||
|
You can also disable annotation processing by specifying _-proc:none_.
|
||||||
|
|
||||||
|
Run `'javac -help'` to see which other annotation processor relevant options can be specified.
|
||||||
|
====
|
||||||
|
|
||||||
|
|
||||||
|
The structure of the metamodel classes is described in the Jakarta Persistence
|
||||||
|
specification, but for completeness the definition is repeated in the following
|
||||||
|
paragraphs. For every class in a persistence-unit, the generator will produce
|
||||||
|
a static metamodel class based on the following rules:
|
||||||
|
|
||||||
|
* For each managed class `X` in package `p`, a metamodel class `X_` is created in package `p`.
|
||||||
|
* The name of the metamodel class is derived from the name of the managed class by appending "_" to the managed class name.
|
||||||
|
* The metamodel class `X_` must be annotated with the `jakarta.persistence.StaticMetamodel` annotation. The generation
|
||||||
|
can also be configured to add the `javax.annotation.processing.Generated` annotation.
|
||||||
|
* If class `X` extends another class `S`, where `S` is the most derived managed class extended by `X`, then
|
||||||
|
class `X_` must extend class `S_`, where `S_` is the metamodel class created for `S`.
|
||||||
|
* For every persistent singular attribute `y` declared by class `X`, where the type of `y` is `Y`,
|
||||||
|
the metamodel class must contain a declaration as follows:
|
||||||
|
|
||||||
|
public static volatile SingularAttribute<X, Y> y;
|
||||||
|
|
||||||
|
* For every persistent plural attribute `z` declared by class `X`, where the element type of `z` is `Z`, the metamodel
|
||||||
|
class must contain a declaration as follows:
|
||||||
|
|
||||||
|
** if the collection type of `z` is `java.util.Collection`, then
|
||||||
|
|
||||||
|
public static volatile CollectionAttribute<X, Z> z;
|
||||||
|
|
||||||
|
** if the collection type of `z` is `java.util.Set`, then
|
||||||
|
|
||||||
|
public static volatile SetAttribute<X, Z> z;
|
||||||
|
|
||||||
|
** if the collection type of `z` is `java.util.List`, then
|
||||||
|
|
||||||
|
public static volatile ListAttribute<X, Z> z;
|
||||||
|
|
||||||
|
** if the collection type of `z` is `java.util.Map`, then
|
||||||
|
+
|
||||||
|
public static volatile MapAttribute<X, K, Z> z;
|
||||||
|
+
|
||||||
|
where `K` is the type of the key of the map in class `X`
|
||||||
|
|
||||||
|
* Import statements must be included for `jakarta.persistence.metamodel` types as
|
||||||
|
needed, as well as all domain model classes (i.e., `X`, `S`, `Y`, `Z`, and `K`).
|
||||||
|
|
||||||
|
As an example, consider the following domain model -
|
||||||
|
|
||||||
|
[[ex-tooling-modelgen-model]]
|
||||||
|
.`Order` and `Item` entities
|
||||||
|
====
|
||||||
|
[source, JAVA, indent=0]
|
||||||
|
----
|
||||||
|
include::{documentationModel}/tooling/Customer.java[tags=tooling-modelgen-model]
|
||||||
|
include::{documentationModel}/tooling/Order.java[tags=tooling-modelgen-model]
|
||||||
|
include::{documentationModel}/tooling/Item.java[tags=tooling-modelgen-model]
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
||||||
|
Given this model, the generator will produce classes named `Customer_`, `Order_` and `Item_`. As an example:
|
||||||
|
|
||||||
|
[[tooling-modelgen-metamodel]]
|
||||||
|
.`Order_`
|
||||||
|
====
|
||||||
|
[source, JAVA, indent=0]
|
||||||
|
----
|
||||||
|
include::{documentationMetamodel}/tooling/Order_.java[]
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
||||||
|
At boot-time, Hibernate will find these classes and populate them. They can then be used in
|
||||||
|
Criteria queries for type-safe path references. For example:
|
||||||
|
|
||||||
|
[[tooling-modelgen-usage]]
|
||||||
|
.Static Metamodel usage
|
||||||
|
====
|
||||||
|
[source, JAVA, indent=0]
|
||||||
|
----
|
||||||
|
include::{toolingTestsDir}/modelgen/ModelGenTests.java[tags=tooling-modelgen-usage]
|
||||||
|
----
|
||||||
|
====
|
||||||
|
|
|
@ -0,0 +1,4 @@
|
||||||
|
[[tooling-schema]]
|
||||||
|
=== Schema Management
|
||||||
|
|
||||||
|
Coming soon
|
|
@ -0,0 +1,39 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.userguide.model.tooling;
|
||||||
|
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.Basic;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
@Table(name = "customers")
|
||||||
|
//tag::tooling-modelgen-model[]
|
||||||
|
@Entity
|
||||||
|
public class Customer {
|
||||||
|
@Id
|
||||||
|
private Integer id;
|
||||||
|
@Basic
|
||||||
|
private String name;
|
||||||
|
|
||||||
|
// getters and setters omitted for brevity
|
||||||
|
//end::tooling-modelgen-model[]
|
||||||
|
|
||||||
|
private Customer() {
|
||||||
|
// for Hibernate use
|
||||||
|
}
|
||||||
|
|
||||||
|
public Customer(Integer id, String name) {
|
||||||
|
this.id = id;
|
||||||
|
this.name = name;
|
||||||
|
}
|
||||||
|
//tag::tooling-modelgen-model[]
|
||||||
|
}
|
||||||
|
//end::tooling-modelgen-model[]
|
|
@ -0,0 +1,45 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.userguide.model.tooling;
|
||||||
|
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.ManyToOne;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
@Table(name = "items")
|
||||||
|
//tag::tooling-modelgen-model[]
|
||||||
|
@Entity
|
||||||
|
public class Item {
|
||||||
|
@Id
|
||||||
|
Integer id;
|
||||||
|
|
||||||
|
int quantity;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
Order order;
|
||||||
|
|
||||||
|
// getters and setters omitted for brevity
|
||||||
|
//end::tooling-modelgen-model[]
|
||||||
|
|
||||||
|
public Item() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Item(Integer id, int quantity, Order order) {
|
||||||
|
this.id = id;
|
||||||
|
this.quantity = quantity;
|
||||||
|
this.order = order;
|
||||||
|
|
||||||
|
order.items.add( this );
|
||||||
|
}
|
||||||
|
|
||||||
|
//tag::tooling-modelgen-model[]
|
||||||
|
}
|
||||||
|
//end::tooling-modelgen-model[]
|
|
@ -0,0 +1,49 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.userguide.model.tooling;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import java.util.Set;
|
||||||
|
import jakarta.persistence.Entity;
|
||||||
|
import jakarta.persistence.Id;
|
||||||
|
import jakarta.persistence.ManyToOne;
|
||||||
|
import jakarta.persistence.OneToMany;
|
||||||
|
import jakarta.persistence.Table;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
//tag::tooling-modelgen-model[]
|
||||||
|
@Entity
|
||||||
|
@Table(name = "orders")
|
||||||
|
public class Order {
|
||||||
|
@Id
|
||||||
|
Integer id;
|
||||||
|
|
||||||
|
@ManyToOne
|
||||||
|
Customer customer;
|
||||||
|
|
||||||
|
@OneToMany
|
||||||
|
Set<Item> items;
|
||||||
|
BigDecimal totalCost;
|
||||||
|
|
||||||
|
// standard setter/getter methods
|
||||||
|
|
||||||
|
//end::tooling-modelgen-model[]
|
||||||
|
|
||||||
|
public Order() {
|
||||||
|
}
|
||||||
|
|
||||||
|
public Order(Integer id, Customer customer, BigDecimal totalCost) {
|
||||||
|
this.id = id;
|
||||||
|
this.customer = customer;
|
||||||
|
this.totalCost = totalCost;
|
||||||
|
}
|
||||||
|
//tag::tooling-modelgen-model[]
|
||||||
|
}
|
||||||
|
//end::tooling-modelgen-model[]
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Hibernate, Relational Persistence for Idiomatic Java
|
||||||
|
*
|
||||||
|
* License: GNU Lesser General Public License (LGPL), version 2.1 or later
|
||||||
|
* See the lgpl.txt file in the root directory or http://www.gnu.org/licenses/lgpl-2.1.html
|
||||||
|
*/
|
||||||
|
package org.hibernate.userguide.tooling.modelgen;
|
||||||
|
|
||||||
|
import java.math.BigDecimal;
|
||||||
|
import jakarta.persistence.criteria.CriteriaBuilder;
|
||||||
|
import jakarta.persistence.criteria.CriteriaQuery;
|
||||||
|
import jakarta.persistence.criteria.Root;
|
||||||
|
|
||||||
|
import org.hibernate.userguide.model.tooling.Customer;
|
||||||
|
import org.hibernate.userguide.model.tooling.Item;
|
||||||
|
import org.hibernate.userguide.model.tooling.Order;
|
||||||
|
import org.hibernate.userguide.model.tooling.Order_;
|
||||||
|
|
||||||
|
import org.hibernate.testing.orm.junit.DomainModel;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactory;
|
||||||
|
import org.hibernate.testing.orm.junit.SessionFactoryScope;
|
||||||
|
import org.junit.jupiter.api.Test;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @author Steve Ebersole
|
||||||
|
*/
|
||||||
|
@DomainModel( annotatedClasses = { Order.class, Item.class, Customer.class } )
|
||||||
|
@SessionFactory
|
||||||
|
public class ModelGenTests {
|
||||||
|
@Test
|
||||||
|
public void testIt(SessionFactoryScope scope) {
|
||||||
|
scope.inTransaction( (session) -> {
|
||||||
|
//tag::tooling-modelgen-usage[]
|
||||||
|
final CriteriaBuilder criteriaBuilder = session.getCriteriaBuilder();
|
||||||
|
final CriteriaQuery<Customer> criteria = criteriaBuilder.createQuery( Customer.class );
|
||||||
|
|
||||||
|
final Root<Order> root = criteria.from( Order.class );
|
||||||
|
|
||||||
|
criteria.select( root.get( Order_.customer ) );
|
||||||
|
criteria.where( criteriaBuilder.greaterThan( root.get( Order_.totalCost ), new BigDecimal( 100 ) ) );
|
||||||
|
//end::tooling-modelgen-usage[]
|
||||||
|
} );
|
||||||
|
}
|
||||||
|
}
|
|
@ -77,6 +77,10 @@ public class JpaMetamodelGenerationSpec {
|
||||||
return applyGeneratedAnnotation;
|
return applyGeneratedAnnotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void applyGeneratedAnnotation(boolean apply) {
|
||||||
|
applyGeneratedAnnotation.set( apply );
|
||||||
|
}
|
||||||
|
|
||||||
public SetProperty<String> getSuppressions() {
|
public SetProperty<String> getSuppressions() {
|
||||||
return suppressions;
|
return suppressions;
|
||||||
}
|
}
|
||||||
|
|
|
@ -300,6 +300,7 @@ public class JpaMetamodelGenerationTask extends DefaultTask {
|
||||||
public static void apply(HibernateOrmSpec ormDsl, SourceSet mainSourceSet, Project project) {
|
public static void apply(HibernateOrmSpec ormDsl, SourceSet mainSourceSet, Project project) {
|
||||||
final String mainCompileTaskName = mainSourceSet.getCompileJavaTaskName();
|
final String mainCompileTaskName = mainSourceSet.getCompileJavaTaskName();
|
||||||
final JavaCompile mainCompileTask = (JavaCompile) project.getTasks().getByName( mainCompileTaskName );
|
final JavaCompile mainCompileTask = (JavaCompile) project.getTasks().getByName( mainCompileTaskName );
|
||||||
|
final Task compileResourcesTask = project.getTasks().getByName( "processResources" );
|
||||||
|
|
||||||
final JpaMetamodelGenerationTask genTask = project.getTasks().create(
|
final JpaMetamodelGenerationTask genTask = project.getTasks().create(
|
||||||
DSL_NAME,
|
DSL_NAME,
|
||||||
|
@ -313,8 +314,6 @@ public class JpaMetamodelGenerationTask extends DefaultTask {
|
||||||
genTask.setDescription( "Generates the JPA 'static metamodel'" );
|
genTask.setDescription( "Generates the JPA 'static metamodel'" );
|
||||||
|
|
||||||
genTask.dependsOn( mainCompileTask );
|
genTask.dependsOn( mainCompileTask );
|
||||||
|
|
||||||
final Task compileResourcesTask = project.getTasks().getByName( "processResources" );
|
|
||||||
genTask.dependsOn( compileResourcesTask );
|
genTask.dependsOn( compileResourcesTask );
|
||||||
|
|
||||||
final JavaCompile compileJpaMetamodelTask = project.getTasks().create( COMPILE_DSL_NAME, JavaCompile.class );
|
final JavaCompile compileJpaMetamodelTask = project.getTasks().create( COMPILE_DSL_NAME, JavaCompile.class );
|
||||||
|
@ -323,6 +322,7 @@ public class JpaMetamodelGenerationTask extends DefaultTask {
|
||||||
compileJpaMetamodelTask.setSourceCompatibility( mainCompileTask.getSourceCompatibility() );
|
compileJpaMetamodelTask.setSourceCompatibility( mainCompileTask.getSourceCompatibility() );
|
||||||
compileJpaMetamodelTask.setTargetCompatibility( mainCompileTask.getTargetCompatibility() );
|
compileJpaMetamodelTask.setTargetCompatibility( mainCompileTask.getTargetCompatibility() );
|
||||||
genTask.finalizedBy( compileJpaMetamodelTask );
|
genTask.finalizedBy( compileJpaMetamodelTask );
|
||||||
|
mainCompileTask.finalizedBy( compileJpaMetamodelTask );
|
||||||
compileJpaMetamodelTask.dependsOn( genTask );
|
compileJpaMetamodelTask.dependsOn( genTask );
|
||||||
compileJpaMetamodelTask.source( project.files( ormDsl.getJpaMetamodelSpec().getGenerationOutputDirectory() ) );
|
compileJpaMetamodelTask.source( project.files( ormDsl.getJpaMetamodelSpec().getGenerationOutputDirectory() ) );
|
||||||
compileJpaMetamodelTask.getDestinationDirectory().set( ormDsl.getJpaMetamodelSpec().getCompileOutputDirectory() );
|
compileJpaMetamodelTask.getDestinationDirectory().set( ormDsl.getJpaMetamodelSpec().getCompileOutputDirectory() );
|
||||||
|
|
Loading…
Reference in New Issue