Hibernate.orgCommunity Documentation
Table of Contents
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 JPA. The process is very different for each.
This chapter will not focus on all the possibilities of bootstrapping. Those will be covered in each specific more-relevant chapters later on. Instead we focus here on the API calls needed to perform the bootstrapping.
This section discusses the process of bootstrapping a Hibernate SessionFactory. Specifically it discusses the bootstrapping APIs as redesigned in 5.0. For a discussion of the legacy bootstrapping API, see Appendix A, Legacy Bootstrapping
The first step in native bootstrapping is the building of a ServiceRegistry holding the services Hibernate will need at bootstrap and run time.
Actually we are concerned with building 2 different ServiceRegistries. First is the
org.hibernate.boot.registry.BootstrapServiceRegistry
. The
BootstrapServiceRegistry is intended to hold services that Hibernate needs at both bootstrap and
run time. This boils down to 3 services:
org.hibernate.boot.registry.classloading.spi.ClassLoaderService
-
which controls how Hibernate interacts with ClassLoaders
org.hibernate.integrator.spi.IntegratorService
-
which controls the management ands discovery of
org.hibernate.integrator.spi.Integrator
instances.
org.hibernate.boot.registry.selector.spi.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), then building the BootstrapServiceRegistry can be skipped.
If you wish to alter how the BootstrapServiceRegistry is built, that is controlled through the
org.hibernate.boot.registry.BootstrapServiceRegistryBuilder
:
Example 4.1. Controlling BootstrapServiceRegistry building
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).
The second ServiceRegistry is the org.hibernate.boot.registry.StandardServiceRegistry
.
You will almost always need to configure the StandardServiceRegistry, which is done through
org.hibernate.boot.registry.StandardServiceRegistryBuilder
:
Example 4.2. Building a BootstrapServiceRegistryBuilder
// An example using an implicitly built BootstrapServiceRegistry StandardServiceRegistryBuilder standardRegistryBuilder = new StandardServiceRegistryBuilder();
// An example using an explicitly built BootstrapServiceRegistry BootstrapServiceRegistry bootstrapRegistry = ...; StandardServiceRegistryBuilder standardRegistryBuilder = new StandardServiceRegistryBuilder( bootstrapRegistry );
A StandardServiceRegistry is also highly configurable via the StandardServiceRegistryBuilder API. See the StandardServiceRegistryBuilder javadocs for full details. Some specific methods of interest:
Example 4.3. Controlling StandardServiceRegistry building
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/my.cfg.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();
The second step in native bootstrapping is the building of a org.hibernate.boot.Metadata
object containing 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
:
Example 4.4. Configuring a 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. But the approach shown // above is preferred // 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:
Example 4.5. Configuring a MetadataSources with method chaining
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 then you can simply call MetadataSources#buildMetadata.
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.
Example 4.6. Building Metadata via MetadataBuilder
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();
The final step in native bootstrapping is to build the SessionFactory itself. Much like 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. Again, see its javadocs for full details.
Example 4.7. Building SessionFactory via SessionFactoryBuilder
SessionFactoryBuilder sessionFactoryBuilder = metadata.getSessionFactoryBuilder(); // Supply an 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();
The bootstrapping API is quite flexible, but in most cases it makes the most sense to think of it as a 3 step process:
Example 4.8. Native Bootstrapping - Putting it all together
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();
Bootstrapping Hibernate as a JPA provider can be done in a JPA-spec compliant manner or using a proprietary bootstrapping approach. The standardized approach has some limitations in certain environments, but aside from those limitations, it is *highly* recommended that you use JPA-standardized bootstrapping.
In JPA we are ultimately interested in bootstrapping an javax.persistence.EntityManagerFactory instance. The JPA specification defines 2 primary standardized bootstrap approaches depending on how the application intends to access the javax.persistence.EntityManager instances from an EntityManagerFactory. It uses the terms "EE" and "SE" for these 2 approaches, but those terms are very misleading in this context. What the JPA spec calls EE bootstrapping is cases where a container (EE, OSGi, etc) 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-bootstrapping and application-bootstrapping in this guide.
For compliant container-bootstrapping, the container will build an EntityManagerFactory for each persistent-unit defined in the deployment's META-INF/persistence.xml and make that available to the application for injection via the javax.persistence.PersistenceUnit annotation or via JNDI lookup.
For compliant application-bootstrapping, rather than the container building the EntityManagerFactory for the application, the application builds the EntityManagerFactory itself using the javax.persistence.Persistence bootstrap class. The application creates an entity manager factory by calling the createEntityManagerFactory method:
Example 4.10. Application bootstrapped EntityManagerFactory
// Create an EMF for our CRM persistence-unit. EntityManagerFactory emf = Persistence.createEntityManagerFactory("CRM");