This guide discusses the process of bootstrapping a Hibernate org.hibernate.SessionFactory
. It also
discusses the ways in which applications and integrators can hook-in to and affect that process. This
bootstrapping process is defined in 2 distinct steps. The first step is the building of a ServiceRegistry
holding the services Hibernate will need at bootstrap- and runtime. The second step is the building of
a Metadata object representing the mapping information for the application’s model and its mapping to
the database.
Prior to version 5.0 applications bootstrapped a SessionFactory is via the
org.hibernate.cfg.Configuration object. That approach is still supported in a slightly limited manner.
See the Legacy Bootstrapping guide for details.
|
Building the ServiceRegistry
Actually we are concerned with building 2 different ServiceRegistries:
-
org.hibernate.boot.registry.BootstrapServiceRegistry
-
org.hibernate.boot.registry.StandardServiceRegistry
Each of these is built from a builder, org.hibernate.boot.registry.BootstrapServiceRegistryBuilder
and org.hibernate.boot.registry.StandardServiceRegistryBuilder
respectively.
For more information on ServiceRegistries in general, see the Services and Registries guide. |
BootstrapServiceRegistry
The BootstrapServiceRegistry
is intended to hold services that Hibernate needs at both bootstrap and run time.
This boils down to 3 services:
-
ClassLoaderService
- which controls how Hibernate interacts with ClassLoaders -
IntegratorService
- which controls the management ands discovery oforg.hibernate.integrator.spi.Integrator
instances. -
StrategySelector
- which control 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.
If you are ok with the default behavior of Hibernate in regards to these BootstrapServiceRegistry services
(which is quite often the case, especially in SE environments) building the BootstrapServiceRegistry can be skipped.
If you wish to alter how the BootstrapServiceRegistry
is built, you would use the BootstrapServiceRegistryBuilder
:
BootstrapServiceRegistryBuilder bootstrapRegistryBuilder
= new BootstrapServiceRegistryBuilder();
// add a special ClassLoader
bootstrapRegistryBuilder.applyClassLoader( mySpecialClassLoader );
// manually add an Integrator
bootstrapRegistryBuilder.applyIntegrator( mySpecialIntegrator );
...
BootstrapServiceRegistry bootstrapRegistry = bootstrapRegistryBuilder.build();
The services of the BootstrapServiceRegistry
cannot be extended (added to) nor overridden (replaced).
StandardServiceRegistry
The services of the StandardServiceRegistry
may be extended and overridden.
A StandardServiceRegistry
is built through the StandardServiceRegistryBuilder
which can be constructed in
one of 2 ways:
BootstrapServiceRegistry bootstrapRegistry = ...;
StandardServiceRegistryBuilder standardRegistryBuilder
= new StandardServiceRegistryBuilder( bootstrapRegistry );
StandardServiceRegistryBuilder standardRegistryBuilder
= new StandardServiceRegistryBuilder();
The second form will create a BootstrapServiceRegistry
on the fly with default behavior.
A StandardServiceRegistry
is also highly configurable via the StandardServiceRegistryBuilder
API. See the
StandardServiceRegistryBuilder
javadocs for full details. Some specific methods of interest:
StandardServiceRegistryBuilder standardRegistryBuilder = ...;
// load some properties via resource lookup
standardRegistryBuilder.loadProperties( "org/hibernate/example/MyProperties.properties" );
// configure the registry from a resource lookup for a cfg.xml config file
standardRegistryBuilder.configure( "org/hibernate/example/MyCfg.xml" );
// apply a random setting
standardRegistryBuilder.applySetting( "myProp", "some value" );
// apply a service initiator
standardRegistryBuilder.addInitiator( new CustomServiceInitiator() );
// apply a service impl
standardRegistryBuilder.addService( SomeCustomService.class, new SomeCustomServiceImpl() );
// and finally build the StandardServiceRegistry
StandardServiceRegistry standardRegistry = standardRegistryBuilder.build();
Building the Metadata
The org.hibernate.boot.Metadata
object contains the parsed representations of an application’s
domain model and its mapping to a database. The first thing we obviously need to build a parsed
representation is the source information to be parsed (annotated classes, hbm.xml
files, orm.xml
files). This is
the purpose of org.hibernate.boot.MetadataSources
.
MetadataSources sources = new MetadataSources( standardRegistry );
// alternatively, we can build the MetadataSources without passing
// a service registry, in which case it will build a default
// BootstrapServiceRegistry to use
// MetadataSources sources = new MetadataSources();
// add a class using JPA/Hibernate annotations for mapping
sources.addAnnotatedClass( MyEntity.class );
// add the name of a class using JPA/Hibernate annotations for mapping.
// differs from above in that accessing the Class is deferred which is
// important if using runtime bytecode-enhancement
sources.addAnnotatedClassName( "org.hibernate.example.Customer" );
// Adds the named hbm.xml resource as a source: which performs the
// classpath lookup and parses the XML
sources.addResource( "org/hibernate/example/Order.hbm.xml" );
// Adds the named JPA orm.xml resource as a source: which performs the
// classpath lookup and parses the XML
sources.addResource( "org/hibernate/example/Product.orm.xml" );
MetadataSources
has many other methods as well; explore its API and javadocs for more information. Also,
all methods on MetadataSources
allow for chaining should you prefer that style.
MetadataSources sources = new MetadataSources( standardRegistry )
.addAnnotatedClass( MyEntity.class )
.addAnnotatedClassName( "org.hibernate.example.Customer" )
.addResource( "org/hibernate/example/Order.hbm.xml" )
.addResource( "org/hibernate/example/Product.orm.xml" );
Once we have the sources of mapping information defined, we need to build the Metadata
object. If you are
ok with the default behavior in building the Metadata
(or if relying on a MetadataBuilderInitializer
- see below)
then you can simply call MetadataSources#buildMetadata
.
NOTE : Notice that a ServiceRegistry can be passed at a number of points in this bootstrapping process. The suggested
approach is to build a StandardServiceRegistry
yourself and pass that along to the MetadataSources
constructor.
From there, MetadataBuilder
, Metadata
, SessionFactoryBuilder
and SessionFactory
will all pick up that
same StandardServiceRegistry
.
However, if you wish to adjust the process of building Metadata
from MetadataSources
you will need to use
the MetadataBuilder
as obtained via MetadataSources#getMetadataBuilder
. MetadataBuilder
allows a lot of control
over the Metadata
building process. See its javadocs for full details.
MetadataBuilder metadataBuilder = sources.getMetadataBuilder();
// Use the JPA-compliant implicit naming strategy
metadataBuilder.applyImplicitNamingStrategy( ImplicitNamingStrategyJpaCompliantImpl.INSTANCE );
// specify the schema name to use for tables, etc when none is explicitly specified
metadataBuilder.applyImplicitSchemaName( "my_default_schema" );
Metadata metadata = metadataBuilder.build();
Building the SessionFactory
Much like we’ve discussed above, if you are ok with the default behavior of building a SessionFactory
from a Metadata
reference, you can simply call Metadata#buildSessionFactory
. However, if you would like to
adjust that building process you will need to use SessionFactoryBuilder
as obtained via
Metadata#getSessionFactoryBuilder
. See the SessionFactoryBuilder
javadocs for details of the control it allows
over the SessionFactory
building process.
SessionFactoryBuilder sessionFactoryBuilder = metadata.getSessionFactoryBuilder();
// Supply a SessionFactory-level Interceptor
sessionFactoryBuilder.applyInterceptor( new MySessionFactoryInterceptor() );
// Add a custom observer
sessionFactoryBuilder.addSessionFactoryObservers( new MySessionFactoryObserver() );
// Apply a CDI BeanManager (for JPA event listeners)
sessionFactoryBuilder.applyBeanManager( getBeanManagerFromSomewhere() );
SessionFactory sessionFactory = sessionFactoryBuilder.build();
Putting It All Together
The bootstrapping API is quite flexible, but in most cases it makes the most sense to think of it as a 3 step process:
-
Build the
StandardServiceRegistry
-
Build the
Metadata
-
Use those 2 things to build the
SessionFactory
StandardServiceRegistry standardRegistry = new StandardServiceRegistryBuilder()
.configure( "org/hibernate/example/MyCfg.xml" )
.build();
Metadata metadata = new MetadataSources( standardRegistry )
.addAnnotatedClass( MyEntity.class )
.addAnnotatedClassName( "org.hibernate.example.Customer" )
.addResource( "org/hibernate/example/Order.hbm.xml" )
.addResource( "org/hibernate/example/Product.orm.xml" )
.getMetadataBuilder()
.applyImplicitNamingStrategy( ImplicitNamingStrategyJpaCompliantImpl.INSTANCE )
.build();
SessionFactory sessionFactory = metadata.getSessionFactoryBuilder()
.applyBeanManager( getBeanManagerFromSomewhere() )
.build();