After the introduction into Hibernate 4 which included mapping relationships and inheritance let’s dig a bit deeper and see how we can reach stored data in the database.
If you looked at the main method of the example application you could see that I was using a simple criteria query generated out of the session to list and count data. Loading all the data to count them is too much and consumes too much memory. There are other ways, let me show them.
HQL and JPQL
HQL is the default query language of Hibernate (the abbreviation stays for Hibernate Query Language). JPQL is for the more general Java Persistence Query Language which is a subset of HQL. This means that a valid JQPL query is a valid HQL query too — but the opposite is not always true.
The main idea behind HQL was that you can use the entity names in the queries instead of the table names in the database. This makes the storage and querying more transparent and you could split the tasks between developers because who writes queries needs only to know the entity name.
The simples HQL query is a select query:
Yes, this is a valid query as you can see in the repository.
If you mention an entity you can use its simple name or the qualified name of the entity (with the whole package structure).
Beside select JPQL and HQL allow update and delete statements. HQL offers additionally insert statements too.
A remark on case sensitivity
The keywords in HQL and JPQL are case insensitive, this means that SELECT, select and SeLeCt mean the same. However entity names are case sensitive: hibernate_example.Book is different from hibernate_example.BOOK.
A remark on type-safety
HQL and JPQL are non-type-safe queries. Criteria queries offer a type-safe approach.
What does type-safety mean? You do not have to cast an Object return value from a query to the desired entity object. That’s why you get compile-time warnings when using Hibernate’s default query mechanisms.
Creating and executing queries
Fortunately creating and executing queries does not require specific libraries, it can be done through the session object we already have in the main method.
To separate queries from the main method I’ve added a Repository class where I implemented some static functions to query the database.
So let’s look at the different versions of query-creation. All have the same root: the Session object but they are executed calling different methods.
Queries are the simplest way to execute queries and this is the most common one:
The usage of criterions enables restrictions on the result set programmatically (you need less typing in the query and can comment out lines of criteria easily when debugging for example):
The query above returns all authors whose name starts with the letter M.
Sometimes it comes handy to write native queries because you need some specific methods only available in the database you are using. Fortunately Hibernate supports native queries too.
Native queries are plain old SQL where you have to use the table name instead of the entity name.
The difference is in the result types. For example counting objects with SQL queries returns a BigInteger using a HQL query we get back a Long. So changing the query time is not always transparent and can cause some nasty bugs in your application.
Why can native queries be better? Because you can eliminate some joins Hibernate does by its nature.
For example counting the Authors with Hibernate query results in the following SQL in the end:
select count(*) from Author a inner join PERSONS p on a.name = p.name
However we know the data structure and we can say we eliminate the join:
return (BigInteger) session.createSQLQuery("select count(*) from author").uniqueResult();
The drawback is naturally that we lose transparency and changing the inheritance model needs to adapt the query.
HQL and JPQL are native query languages coming along with Hibernate. They can be used without any pre-requisites. However they are non-type-safe which means you have to cast the results to the according type which can lead to runtime exceptions if the casting cannot be done.
In this article I did not show criteria queries, parametrized and prepared statements — but I will do it in articles later on in the future.
You can download chapter specific code from Github Here.