Working with both Object-Oriented software and Relational Databases can be cumbersome and time-consuming.Development costs are significantly higher due to a number of "paradigm mismatches" between how data is represented in objectsversus relational databases. Hibernate is an Object/Relational Mapping (ORM) solution for Java environments. Theterm Object/Relational Mapping refers to the technique of mapping data between an object model representation toa relational data model representation. Seehttps://en.wikipedia.org/wiki/Object-relational_mapping for a goodhigh-level discussion. Also, Martin Fowler’sOrmHate articletakes a look at many of the mismatch problems.
Although having a strong background in SQL is not required to use Hibernate, having a basic understanding of theconcepts can help you understand Hibernate more quickly and fully. An understanding of data modeling principlesis especially important. Bothhttps://www.agiledata.org/essays/dataModeling101.html andhttps://en.wikipedia.org/wiki/Data_modeling are good starting points for understanding these data modelingprinciples. If you are completely new to database access in Java,https://www.marcobehler.com/guides/a-guide-to-accessing-databases-in-java contains a good overview of the various parts,pieces and options.
Hibernate takes care of the mapping from Java classes to database tables, and from Java data types to SQL datatypes. In addition, it provides data query and retrieval facilities. It can significantly reduce developmenttime otherwise spent with manual data handling in SQL and JDBC. Hibernate’s design goal is to relieve thedeveloper from 95% of common data persistence-related programming tasks by eliminating the need for manual,hand-crafted data processing using SQL and JDBC. However, unlike many other persistence solutions, Hibernatedoes not hide the power of SQL from you and guarantees that your investment in relational technology andknowledge is as valid as always.
Hibernate may not be the best solution for data-centric applications that only use stored-procedures toimplement the business logic in the database, it is most useful with object-oriented domain models and businesslogic in the Java-based middle-tier. However, Hibernate can certainly help you to remove or encapsulatevendor-specific SQL code and streamlines the common task of translating result sets from a tabularrepresentation to a graph of objects.
Seehttps://hibernate.org/orm/contribute/ for information on getting involved.
| The projects and code for the tutorials referenced in this guide are available ashibernate-tutorials.zip |
Hibernate’s functionality is split into a number of modules/artifacts meant to isolate dependencies (modularity).
The main (core) Hibernate module. Defines its ORM features and APIs as well as the various integration SPIs.
Hibernate’s historical entity versioning feature
Hibernate’s Spatial/GIS data-type support
Hibernate support for running in OSGi containers.
Integrates theAgroal connection pooling library into Hibernate
Integrates theC3P0 connection pooling library into Hibernate
Integrates theHikariCP connection pooling library into Hibernate
Integrates theVibur DBCP connection pooling library into Hibernate
Integrates theProxool connection pooling library into Hibernate
Integrates theJCache caching specification into Hibernate,enabling any compliant implementation to become a second-level cache provider.
Integrates theEhcache caching library into Hibernate as a second-level cache provider.
The Hibernate team provides release bundles hosted on the SourceForge File Release System, in bothTGZ andZIP formats. Each release bundle containsJAR files, documentation, source code, and other goodness.
You can download releases of Hibernate, in your chosen format, from the list athttps://sourceforge.net/projects/hibernate/files/hibernate-orm/. The release bundle is structured as follows:
Thelib/required/ directory contains thehibernate-core jar and all of its dependencies. All of these jars arerequired to be available on your classpath no matter which features of Hibernate are being used.
Thelib/envers directory contains thehibernate-envers jar and all of its dependencies (beyond those inlib/required/ andlib/jpa/).
Thelib/spatial/ directory contains thehibernate-spatial jar and all of its dependencies (beyond those inlib/required/)
Thelib/osgi/ directory contains thehibernate-osgi jar and all of its dependencies (beyond those inlib/required/ andlib/jpa/)
Thelib/jpa-metamodel-generator/ directory contains the jar needed for generating the Criteria API type-safe Metamodel.
Thelib/optional/ directory contains the jars needed for the various connection pooling and second-level cache integrationsprovided by Hibernate, along with their dependencies.
The authoritative repository for Hibernate artifacts is the JBoss Maven repository. The Hibernate artifacts aresynced to Maven Central as part of an automated job (some small delay may occur).
The team responsible for the JBoss Maven repository maintains a number of Wiki pages that contain important information:
https://community.jboss.org/docs/DOC-14900 - General information about the repository.
https://community.jboss.org/docs/DOC-15170 - Information about setting up the JBoss repositories in order to dodevelopment work on JBoss projects themselves.
https://community.jboss.org/docs/DOC-15169 - Information about setting up access to the repository to use JBossprojects as part of your own software.
The Hibernate ORM artifacts are published under theorg.hibernate groupId.
This tutorial is located within the download bundle underbasic/. |
Bootstrap a HibernateSessionFactory
Use Hibernate mapping (hbm.xml) files to provide mapping information
Use the Hibernate native APIs
For this tutorial, thehibernate.cfg.xml file defines the Hibernate configuration information.
Theconnection.driver_class,connection.url,connection.username andconnection.password<property/> elementsdefine JDBC connection information. These tutorials utilize the H2 in-memory database, so the values of these propertiesare all specific to running H2 in its in-memory mode.connection.pool_size is used to configure the number ofconnections in Hibernate’s built-in connection pool.
| The built-in Hibernate connection pool is in no way intended for production use. It lacks severalfeatures found on production-ready connection pools. |
Thedialect property specifies the particular SQL variant with which Hibernate will converse.
| In most cases, Hibernate is able to properly determine which dialect to use. This is particularly usefulif your application targets multiple databases. |
Thehbm2ddl.auto property enables automatic generation of database schemas directly into the database.
Finally, add the mapping file(s) for persistent classes to the configuration. Theresource attribute of the<mapping/> element causes Hibernate to attempt to locate that mapping as a classpath resource using ajava.lang.ClassLoader lookup.
There are many ways and options to bootstrap a HibernateSessionFactory. For additional details, seetheNative Bootstrapping topical guide.
The entity class for this tutorial isorg.hibernate.tutorial.hbm.Event
This class uses standard JavaBean naming conventions for property getter and setter methods, as well asprivate visibility for the fields. Although this is the recommended design, it is not required.
The no-argument constructor, which is also a JavaBean convention, is a requirement for all persistent classes.Hibernate needs to create objects for you, using Java Reflection. The constructor can be private. However, packageor public visibility is required for runtime proxy generation and efficient data retrieval without bytecodeinstrumentation.
The mapping file for this tutorial is the classpath resourceorg/hibernate/tutorial/hbm/Event.hbm.xml (as discussed above).
Hibernate uses the mapping metadata to determine how to load and store objects of the persistent class. The Hibernatemapping file is one choice for providing Hibernate with this metadata.
<class name="Event" table="EVENTS">...</class>Thename attribute (combined here with thepackage attribute from the containing<hibernate-mapping/> element)names the FQN of the class to be defined as an entity.
Thetable attribute names the database table which contains the data for this entity.
Instances of theEvent class are now mapped to rows in theEVENTS database table.
<id name="id" column="EVENT_ID"> ...</id>Hibernate uses the property named by the<id/> element to uniquely identify rows in the table.
| It is not required for the id element to map to the table’s actual primary key column(s), but it isthe normal convention. Tables mapped in Hibernate do not even need to define primary keys. However, it is stronglyrecommend that all schemas define proper referential integrity. Therefore id and primary key are used interchangeablythroughout Hibernate documentation. |
The<id/> element here names the EVENT_ID column as the primary key of the EVENTS table. It also identifies theid property of theEvent class as the property containing the identifier value.
Thegenerator element informs Hibernate about which strategy is used to generated primary key values for this entity.This example uses a simple incrementing count.
<property name="date" type="timestamp" column="EVENT_DATE"/><property name="title"/>The two<property/> elements declare the remaining two persistent properties of theEvent class:date andtitle.Thedate property mapping includes thecolumn attribute, but thetitle does not.In the absence of acolumn attribute, Hibernate uses the property name as the column name.This is appropriate fortitle, but sincedate is a reserved keyword in most databases, you need to specify anon-reserved word for the column name.
Thetitle mapping also lacks a type attribute. The types declared and used in the mapping files are neither Java datatypes nor SQL database types. Instead, they areHibernate mapping types, which are converters which translate betweenJava and SQL data types. Hibernate attempts to determine the correct conversion and mapping type autonomously if thetype attribute is not specified in the mapping, by using Java reflection to determine the Java type of the declaredproperty and using a default mapping type for that Java type.
In some cases this automatic detection might not chose the default you expect or need, as seen with thedate property. Hibernate cannot know if the property, which is of typejava.util.Date, should map to a SQLDATE,TIME, orTIMESTAMP datatype. Full date and time information is preserved by mapping the property tothetimestamp converter, which identifies the converter classorg.hibernate.type.TimestampType.
| Hibernate determines the mapping type using reflection when the mapping files are processed. This process addsoverhead in terms of time and resources. If startup performance is important, consider explicitly defining the typeto use. |
Theorg.hibernate.tutorial.hbm.NativeApiIllustrationTest class illustrates using the Hibernate native API.
The examples in these tutorials are presented as JUnit tests, for ease of use. One benefit of thisapproach is thatsetUp andtearDown roughly illustrate how aorg.hibernate.SessionFactory is created at thestart-up of an application and closed at the end of the application lifecycle. |
org.hibernate.SessionFactoryprotected void setUp() throws Exception {// A SessionFactory is set up once for an application!final StandardServiceRegistry registry = new StandardServiceRegistryBuilder().configure() // configures settings from hibernate.cfg.xml.build();try {sessionFactory = new MetadataSources( registry ).buildMetadata().buildSessionFactory();}catch (Exception e) {// The registry would be destroyed by the SessionFactory, but we had trouble building the SessionFactory// so destroy it manually.StandardServiceRegistryBuilder.destroy( registry );}}ThesetUp method first builds aorg.hibernate.boot.registry.StandardServiceRegistry instance which incorporatesconfiguration information into a working set of Services for use by the SessionFactory. In this tutorialwe defined all configuration information inhibernate.cfg.xml so there is not much interesting to see here.
Using theStandardServiceRegistry we create theorg.hibernate.boot.MetadataSources which is the start point fortelling Hibernate about your domain model. Again, since we defined that inhibernate.cfg.xml so there is not muchinteresting to see here.
org.hibernate.boot.Metadata represents the complete, partially validated view of the application domain model which theSessionFactory will be based on.
The final step in the bootstrap process is to build theSessionFactory. TheSessionFactory is athread-safe object that is instantiated once to serve the entire application.
TheSessionFactory acts as a factory fororg.hibernate.Session instances, which should be thought ofas a corollary to a "unit of work".
Session session = sessionFactory.openSession();session.beginTransaction();session.save( new Event( "Our very first event!", new Date() ) );session.save( new Event( "A follow up event", new Date() ) );session.getTransaction().commit();session.close();testBasicUsage() first creates some newEvent objects and hands them over to Hibernate for management, using thesave() method. Hibernate now takes responsibility to perform anINSERT on the database for eachEvent.
session = sessionFactory.openSession();session.beginTransaction();List result = session.createQuery( "from Event" ).list();for ( Event event : (List<Event>) result ) { System.out.println( "Event (" + event.getDate() + ") : " + event.getTitle() );}session.getTransaction().commit();session.close();Here we see an example of the Hibernate Query Language (HQL) to load all existingEvent objects from the databaseby generating the appropriateSELECT SQL, sending it to the database and populatingEvent objects with the resultset data.
Reconfigure the examples to connect to your own persistent relational database.
Add an association to theEvent entity to model a message thread.
This tutorial is located within the download bundle underannotations/. |
Bootstrap a HibernateSessionFactory
Use annotations to provide mapping information
Use the Hibernate native APIs
The contents are identical toThe Hibernate configuration file with one important difference…The<mapping/> element at the very end naming the annotated entity class using theclass attribute.
The entity class in this tutorial isorg.hibernate.tutorial.annotations.Event which follows JavaBean conventions.In fact the class itself is identical to the one inThe entity Java class, except that annotationsare used to provide the metadata, rather than a separate mapping file.
@Entity@Table( name = "EVENTS" )public class Event { ...}The@javax.persistence.Entity annotation is used to mark a class as an entity. It functions the same as the<class/> mapping element discussed inThe mapping file. Additionally the@javax.persistence.Table annotation explicitly specifies the table name. Without this specification, the defaulttable name would beEVENT.
@Id@GeneratedValue(generator="increment")@GenericGenerator(name="increment", strategy = "increment")public Long getId() { return id;}@javax.persistence.Id marks the property which defines the entity’s identifier.
@javax.persistence.GeneratedValue and@org.hibernate.annotations.GenericGenerator work in tandemto indicate that Hibernate should use Hibernate’sincrement generation strategy for this entity’s identifier values.
public String getTitle() { return title;}@Temporal(TemporalType.TIMESTAMP)@Column(name = "EVENT_DATE")public Date getDate() { return date;}As inThe mapping file, thedate property needs special handling to account for its specialnaming and its SQL type.
Attributes of an entity are considered persistent by default when mapping with annotations, which is why we don’t seeany mapping information associated withtitle.
org.hibernate.tutorial.annotations.AnnotationsIllustrationTest is essentially the same asorg.hibernate.tutorial.hbm.NativeApiIllustrationTest discussed inExample code.
Add an association to theEvent entity to model a message thread. Use theUser Guide for more details.
Add a callback to receive notifications when anEvent is created, updated or deleted.Try the same with an event listener. Use theUser Guide for more details.
This tutorial is located within the download bundle underentitymanager/. |
Bootstrap a JPAEntityManagerFactory
Use annotations to provide mapping information
Use JPA API calls
The previous tutorials used the Hibernate-specifichibernate.cfg.xml configuration file. JPA, however, definesa different bootstrap process that uses its own configuration file namedpersistence.xml. This bootstrapping processis defined by the JPA specification. In Java™ SE environments the persistence provider (Hibernate in this case)is required to locate all JPA configuration files by classpath lookup of theMETA-INF/persistence.xml resource name.
<persistence xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_2_0.xsd" version="2.0"> <persistence-unit name="org.hibernate.tutorial.jpa"> ... </persistence-unit></persistence>persistence.xml files should provide a unique name for each "persistence unit". Applications use this name toreference the configuration when obtaining anjavax.persistence.EntityManagerFactory reference.
The settings defined in the<properties/> element are discussed inThe Hibernate configuration file.Here thejavax.persistence-prefixed varieties are used when possible. Notice that the remainingHibernate-specific configuration setting names are now prefixed withhibernate..
Additionally, the<class/> element functions the same as we saw inThe Hibernate configuration file.
The entity is exactly the same as inThe annotated entity Java class.
The previous tutorials used the Hibernate native APIs. This tutorial uses the JPA APIs.
protected void setUp() throws Exception {sessionFactory = Persistence.createEntityManagerFactory( "org.hibernate.tutorial.jpa" );}Notice again that the persistence unit name isorg.hibernate.tutorial.jpa, which matchespersistence.xml.
EntityManager entityManager = sessionFactory.createEntityManager();entityManager.getTransaction().begin();entityManager.persist( new Event( "Our very first event!", new Date() ) );entityManager.persist( new Event( "A follow up event", new Date() ) );entityManager.getTransaction().commit();entityManager.close();The code is similar toSaving entities. Thejavax.persistence.EntityManager interfaceis used instead of theorg.hibernate.Session interface. JPA calls this operation "persist" instead of "save".
entityManager = sessionFactory.createEntityManager();entityManager.getTransaction().begin();List<Event> result = entityManager.createQuery( "from Event", Event.class ).getResultList();for ( Event event : result ) {System.out.println( "Event (" + event.getDate() + ") : " + event.getTitle() );}entityManager.getTransaction().commit();entityManager.close();Again, the code is pretty similar to what we saw inObtaining a list of entities.
Develop an EJB Session bean to investigate implications of using a container-managedpersistence context. Try both stateless and stateful use-cases.
Use listeners with CDI-based injection to develop a JMS-based event message hub
This tutorial is located within the download bundle underenvers/. |
Annotate an entity as historical
Configure Envers
Use the Envers APIs to view and analyze historical data
This file was discussed in the JPA tutorial inpersistence.xml, and is essentially the same here.
Again, the entity is largely the same as inThe annotated entity Java class. The major difference is theaddition of the@org.hibernate.envers.Audited annotation, which tells Envers to automatically track changes to thisentity.
The code saves some entities, makes a change to one of the entities and then uses the Envers API to pull back theinitial revision as well as the updated revision. A revision refers to a historical snapshot of an entity.
org.hibernate.envers.AuditReaderpublic void testBasicUsage() { ... AuditReader reader = AuditReaderFactory.get( entityManager ); Event firstRevision = reader.find( Event.class, 2L, 1 ); ... Event secondRevision = reader.find( Event.class, 2L, 2 ); ...}We see that anorg.hibernate.envers.AuditReader is obtained from theorg.hibernate.envers.AuditReaderFactorywhich wraps thejavax.persistence.EntityManager.
Next, thefind method retrieves specific revisions of the entity. The first call says to find revision number1 of Event with id 2. The second call says to find revision number 2 of Event with id 2.
Provide a custom revision entity to additionally capture who made the changes.
Write a query to retrieve only historical data which meets some criteria. Use theUser Guide to see howEnvers queries are constructed.
Experiment with auditing entities which have various forms of relationships (many-to-one, many-to-many, etc). Tryretrieving historical versions (revisions) of such entities and navigating the object tree.