The term bootstrapping refers to initializing and starting a software component.
In Hibernate, we are specifically talking about the process of building a fully functional SessionFactory
instance
(or EntityManagerFactory
instance, for Jakarta Persistence).
Tip
|
In this chapter, we will discuss on a number of specific configuration settings. Be sure to check out the appendices/SettingsReference.adoc section as well for documentation of each available setting. |
Hibernate supports both native and standardized approaches for
bootstrapping the SessionFactory
/ EntityManagerFactory
.
Jakarta Persistence defines two standardized bootstrap approaches depending on the environment into which the application is deployed
and on how the application intends to access the EntityManager
instances from an EntityManagerFactory
.
It uses the terms EE and SE for these two approaches, but those terms are very misleading in this context. What Jakarta Persistence calls EE bootstrapping implies the existence of a container (EE, OSGi, etc.) that will manage and inject the persistence context on behalf of the application. What it calls SE bootstrapping is everything else. We will use the terms container and application bootstrapping in this guide.
Note
|
If you would like additional details on accessing and using |
For compliant container-bootstrapping, the container will build an EntityManagerFactory
for each persistent-unit defined in the META-INF/persistence.xml
configuration file
and make that available to the application for injection via the jakarta.persistence.PersistenceUnit
annotation or via JNDI lookup.
In these container environments, an EntityManager
may be dependency injected via @PersistenceContext
. In most
cases, the lifecycle of such an injected EntityManager
is managed by the container.
Consider the following META-INF/persistence.xml
file:
link:extras/persistence.xml[role=include]
We can inject the EntityManagerFactory
-
EntityManagerFactory
link:../../../../../../../hibernate-core/src/test/java/org/hibernate/orm/test/bootstrap/BootstrapTest.java[role=include]
Because there is only one <persistence-unit/>
defined, we can also omit the name and inject the "default" EntityManagerFactory
-
EntityManagerFactory
link:../../../../../../../hibernate-core/src/test/java/org/hibernate/orm/test/bootstrap/BootstrapTest.java[role=include]
See the documentation of your container for additional details.
Jakarta Persistence also allows for the application itself to manage bootstrapping the EntityManagerFactory
reference it needs.
This is achieved through jakarta.persistence.Persistence
or jakarta.persistence.PersistenceConfiguration
.
The traditional way an application builds an EntityManagerFactory
itself is to use jakarta.persistence.Persistence
and either -
-
a
peristence.xml
file -
manually passing a
Map
of settings
EntityManagerFactory
link:../../../../../../../hibernate-core/src/test/java/org/hibernate/orm/test/bootstrap/BootstrapTest.java[role=include]
Jakarta Persistence 3.2 also introduced a new way for applications to build the EntityManagerFactory
itself using
jakarta.persistence.PersistenceConfiguration
which offers a more type-safe approach.
link:../../../../../../../hibernate-core/src/test/java/org/hibernate/orm/test/jpa/boot/PersistenceConfigurationTests.java[role=include]
Hibernate offers an extension to jakarta.persistence.PersistenceConfiguration
named org.hibernate.jpa.HibernatePersistenceConfiguration
which exposes additional conveniences.
link:../../../../../../../hibernate-core/src/test/java/org/hibernate/orm/test/jpa/boot/PersistenceConfigurationTests.java[role=include]
When performing standardized Jakarta Persistence bootstrapping, Hibernate still uses its native under the covers. Therefore, all extension/integration points discussed in that section are also available. It is especially useful in such cases that the integrations are discoverable as Java services.
Hibernate exposes its own approaches for bootstrapping a SessionFactory
-
-
a simplified approach using
Configuration
-
more controlled builder-style approach
org.hibernate.cfg.Configuration
provides a simple API for bootstrapping a Hibernate SessionFactory
.
It is a collection of settings and mappings, thrown together, and used to build the SessionFactory
.
Note
|
Even simplified bootstrapping uses the builder-style approach under the covers, so the integration points discussed there are still available. |
You can obtain the Configuration
by instantiating it directly.
You then specify mapping metadata (XML mapping documents, annotated classes) that describe your applications object model and its mapping to a SQL database.
Configuration cfg = new Configuration()
// addResource does a classpath resource lookup
.addResource( "Item.hbm.xml" )
.addResource( "Bid.hbm.xml" )
// calls addResource using "/org/hibernate/auction/User.hbm.xml"
.addClass( org.hibernate.auction.User.class )
// parses Address class for mapping annotations
.addAnnotatedClass( Address.class )
// reads package-level (package-info.class) annotations in the named package
.addPackage( "org.hibernate.auction" )
.setProperty( "hibernate.dialect", "org.hibernate.dialect.H2Dialect" )
.setProperty( "hibernate.connection.datasource", "java:comp/env/jdbc/test" )
.setProperty( "hibernate.order_updates", "true" );
There are other ways to specify Configuration information, including:
-
Place a file named hibernate.properties in a root directory of the classpath
-
Pass an instance of java.util.Properties to
Configuration#setProperties
-
Via a
hibernate.cfg.xml
file -
System properties using Java
-Dproperty=value
Bootstrapping a SessionFactory
may also be achieved using a number of builders. This approach is broken down into 3 course phases.
First, a ServiceRegistry
is built, which represents the various services that will be available.
An example of such a service is ConnectionProvider
which Hibernate uses to obtain JDBC Connections.
See Building the ServiceRegistry.
Next, a Metadata
is built, which represents the application’s mapping information (entities, embeddables, generators, etc).
See Building the Metadata.
And finally, the SessionFactory
is built.
See Building the SessionFactory.
While "more complex", these builders represents the actual process Hibernate goes through to build a SessionFactory
.
And more importantly, illustrate the various integration points in this bootstrap process.
Note
|
Notice that a |
As mentioned earlier, Hibernate needs a ServiceRegistry
holding the services Hibernate will need during bootstrap and at run time.
Actually, there are 2 types of registries which are important here.
First is the org.hibernate.boot.registry.BootstrapServiceRegistry
which contains 3 important services:
org.hibernate.boot.registry.classloading.spi.ClassLoaderService
-
which controls how Hibernate interacts with
ClassLoader
s. org.hibernate.integrator.spi.IntegratorService
-
which controls the management and discovery of
org.hibernate.integrator.spi.Integrator
instances. org.hibernate.boot.registry.selector.spi.StrategySelector
-
which controls how Hibernate resolves implementations of various strategy contracts. This is a very powerful service, but a full discussion of it is beyond the scope of this guide.
Note
|
If you are ok with the default behavior of Hibernate in regard to these |
If you wish to alter how the BootstrapServiceRegistry
is built, that is controlled through the org.hibernate.boot.registry.BootstrapServiceRegistryBuilder
:
BootstrapServiceRegistry
buildinglink:../../../../../../../hibernate-core/src/test/java/org/hibernate/orm/test/bootstrap/BootstrapTest.java[role=include]
The second registry is the org.hibernate.boot.registry.StandardServiceRegistry
.
You will almost always need to configure this registry, which is done through org.hibernate.boot.registry.StandardServiceRegistryBuilder
:
BootstrapServiceRegistryBuilder
link:../../../../../../../hibernate-core/src/test/java/org/hibernate/orm/test/bootstrap/BootstrapTest.java[role=include]
See the StandardServiceRegistryBuilder
Javadocs for more details.
The main integration point in this process is org.hibernate.service.spi.ServiceContributor
, usually provided
as a Java service, which allows contributing custom Hibernate services.
To build the Metadata
reference, we first construct a MetadataSources
which allows specifying the different sources for mapping information.
This mapping information might be in the form of XML, annotations or both.
MetadataSources
link:../../../../../../../hibernate-core/src/test/java/org/hibernate/orm/test/bootstrap/BootstrapTest.java[role=include]
Also, all methods on MetadataSources
offer fluent-style call chaining -
MetadataSources
with method chaininglink:../../../../../../../hibernate-core/src/test/java/org/hibernate/orm/test/bootstrap/BootstrapTest.java[role=include]
MetadataSources
has many other methods as well. Explore its API and Javadocs for more information.
Once we have the sources of mapping information defined, we need to build the Metadata
object.
If you have specified everything as settings, or you are ok with the default behavior, you can simply call MetadataSources#buildMetadata
.
MetadataSources#buildMetadata
link:../../../../../../../hibernate-core/src/test/java/org/hibernate/orm/test/bootstrap/BootstrapTest.java[role=include]
Optionally, we can obtain a MetadataBuilder
from MetadataSources
which can be used to configure the interpretation of the mapping information.
MetadataBuilder
link:../../../../../../../hibernate-core/src/test/java/org/hibernate/orm/test/bootstrap/BootstrapTest.java[role=include]
There are a few integration points, usually provided as Java services, that hook into this part of bootstrapping -
-
org.hibernate.boot.model.TypeContributor
which allows contributing custom types such as Java type descriptors, JDBC type descriptors, etc. -
org.hibernate.boot.spi.MetadataSourcesContributor
which allows access toMetadataSources
to contribute additional sources. -
org.hibernate.boot.spi.AdditionalMappingContributor
which, likeMetadataSourcesContributor
, allows contributing additional sources. -
org.hibernate.boot.spi.MetadataBuilderInitializer
which allows for configuration ofMetadataBuilder
Once we have Metadata
, we can build the SessionFactory
.
If all configuration has been done by settings, or if you are ok with the default behavior, you can simply call
Metadata#buildSessionFactory
.
SessionFactoryBuilder
link:../../../../../../../hibernate-core/src/test/java/org/hibernate/orm/test/bootstrap/BootstrapTest.java[role=include]
Or a SessionFactoryBuilder
, obtained from Metadata
, may be used to configure the SessionFactory
creation.
SessionFactoryBuilder
link:../../../../../../../hibernate-core/src/test/java/org/hibernate/orm/test/bootstrap/BootstrapTest.java[role=include]
The main integration point here is org.hibernate.integrator.spi.Integrator
, usually provided
as a Java service, which allows contributing custom Hibernate services.
A common use case for Integrator
, for example, is to hook in custom event listeners -
link:../../../../../../../hibernate-core/src/test/java/org/hibernate/orm/test/bootstrap/BootstrapTest.java[role=include]