Hibernate is an open-source project sponsored by RedHat. One of its commonly used components is the Hibernate Object-relational mapping (ORM) which helps developers access databases using an object-oriented approach.
Hibernate is helping developers achieve consistency and persistence in their application, using the data language and objects the developers are already familiar with.
Hibernate ORM will add another layer on top of the regular SQL most are familiar with, to allow you to use objects, properties and functions, instead of writing SQL queries when accessing the database.
- Value Granularity - Using objects to expose columnar data to the user will allow you to have much more granularity in expressing the different entities when compared to the regular relational model. As an example, when storing an address in a single column in a table, you’re in fact storing several smaller entities, like zipcode, street, and country. Accessing this data using an object can allow you to easily reference the different parts without knowing the internal structure of the data.
- Object-Oriented interface - Hibernate ORM allows you to develop object-oriented persistent classes with all known functionality like polymorphism, inheritance, and association. ORM requires no SQL interfaces and allows all classes to be persistent.
- Subtypes - can be also called ‘Inheritance’, This is a known feature in object-oriented languages. However, most relational databases don’t provide anything similar.
Some databases, like PostgreSQL, do have subtype support but it is not common:
CREATE TABLE first ( id serial, primary key(id) );
CREATE TABLE second (primary key(id)) INHERITS (first);
- Identity - Relational databases define one method of 'sameness': the primary key. Other program languages like Java, allow you to define both object identity JohnA==JohnB and object equality JohnA.equals(JohnB).
- Java Persistence Provider - In addition to its own API, Hibernate ORM is also an implementation of the Java Persistence API, also known as JPA specification. This API can be used in SE applications, OSGI containers, and more.
- Automatic SQL generation and enhanced fetching strategies - Hibernate supports several fetching strategies, optimistic locking with automatic versioning, and time stamping. Hibernate ORM doesn’t need unique fields or new database tables, it usually generates the SQL at system initialization and not on the fly, during runtime.
- Scalability - Hibernate ORM supports server clusters and can be implemented on high availability infrastructure.
- Reliable - Hibernate provides stability and quality and is used by thousands of Java engineers across the globe.
- Extensibility - Hibernate can be configured and adjusted to your needs in many different ways. However, in some cases complex configurations may require professional services or using 3rd party applications.
- Low performance for complex database structure and complex queries - Hibernate generates dynamic SQL queries, which in many cases is more than enough for the average application’s needs. However, when queries get more complex, when the amount of entities gets larger, and the amount of data gets larger, the auto-generated queries may under-perform when compared to more optimal queries that can be written using native SQL.
As an example, in this discussion (2.8K views), that discuss that trusting the default database optimizer is not always the right thing to do.
Here is another example of a complex HQL that returns an endless loop, by default. You can fix it, but then again, maybe it is easier to work with Native SQL in this case.
You can also see that the Hibernate team invests time in improving the framework’s auto-generated queries and performance, but it’s a constant work in progress.
- Still requires manual optimization work - Hibernate will write the queries for you, but it won’t handle everything you need to optimize your databases. For example, you still have to decide which indexes to create to optimize your SQL queries.
- Object-Oriented mismatch - OOM means that object models and relational models do not work very well together. Relational databases represent data in a tabular format, whereas object-oriented languages, such as C++ or Java, represent it as an interconnected graph of objects. In general, if you would like to store or load graphs of objects using tables, it might create issues during deployment.
- Data Exploration - When working with databases, you navigate the data using SQL, however, when using Java and Hibernate, you navigate using classes and objects. This method is very useful for developers, however, if you have many tables and entities in the database, the ORM engine may create very complex queries that will slow down the database and application. If you are using the Hibernate ORM, we recommend that you simplify the table structure.
- Hibernate requires expertise - You can work with Hibernate in different ways; for example, you can fetch data using FetchType.Eager strategy or FetchType.Lazy, depending on your data and requirements. Another example is knowing when it is better to use strategy = SEQUENCE vs. Strategy = IDENTITY. Using the framework optimally will require you to understand the different options and configurations and adjust them to your needs.
- Associations - This means that there are unidirectional references in Object-Oriented languages, compared to RDBMSs which use the concept of foreign keys. If you need bi-directional relationships in Java, you should define two associations.
- No easy way to hint the RDBMS Optimizer - HQL (Hibernate Query Language) is translated to SQL, and if the database decides that a specific index makes sense to be used for the SQL query, it will be used automatically.
There is a workaround where you can create your Interceptor by extending org.hibernate.EmptyInterceptor and overwriting onPrepareStatement, but it requires additional coding work.
- Using ORM doesn’t mean that you don’t need to optimize your database -
Here is an example where a customer suffered from slow performance and had to fix the binding parameters.
How to fix performance issues when using Hibernate ORM?
- You can read the ORM documentation to make sure you properly configured and you’re properly using the framework to match your needs (for example, using an eager vs lazy fetch type).
- Analyze your database performance; In many cases, missing indexes or redundant indexes are the root cause for many of these slow queries and performance issues. You can use EverSQL Free Index Advisor for that.
- Over time, as the application matures, we often see companies turn to use a combination of both ORM and native SQL, depending on the use case. To optimize those complex queries that slow down your application, you can use online sql query optimization tools that will rewrite your query and index it for you, automatically.