Sunday, March 1, 2009

Hibernate (Java) explained in English

I'm going to explain Hibernate in as easy to understand terms as I can.
Hibernate is a tremendously popular open source Java Object-Relational-Mapping (ORM). An ORM is a library or layer of code to handle the inherent differences between an Object-Oriented Programming Language (such as Java) and a relational database (such as Postgres, MySQL, Oracle, or Microsoft SQL Server).

An ORM helps a software developer solve a few problems dealing with an Object Oriented Programming Language program that uses a database to store information. The available open source and proprietary ORMs have a number of different features, but all of them offer the first point below. Hibernate offers all of the following:

1. In relational databases, the relationships between objects are indicated by foreign keys. For example, assume there is a table with the name "address", and the primary key (the unique identifier of each row) is "address_id". If a table named "customer" is linked to address, with one address per customer, then the customer table has a column "address_id" that refers to the "address_id" on the "address" table.

In an Object Oriented language, the object relationships are indicated by object links relationships. The Java class Customer probably has a function (also known as method) getAddress which returns the Address object.

An ORM helps handle the conceptual mismatch between the database foreign key relationships and the programming language object links.

2. Hibernate helps handle much of the heavy lifting of your database work. If you have a list of customer order objects in your programming language, it can automatically generate the primary keys and save them in the database with the appropriate data and foreign keys in place. Likewise it can load objects for you.

It can also navigate the programming language object hierarchy and transparently load database objects for you. If your program has order.getCustomer().getPaymentMethods(), that can refer to three tables in the database, "order", "customer", and "payment_method", and your ORM can load the data into the objects for you.

3. Hibernate can do lazy loading to reduce the amount of database traffic. For instance, let's say you have tables "customer" and "order" and "order" has a foreign key reference to customer. In your Java code, this might be represented as a function returning a Set or List customer.getOrders(). Hibernate can navigate the object graph and load this for you. But it won't actually do it until you call getOrders() in your code. This saves a lot of unnecessary database queries every time a customer object is accessed. On the other hand, you can always specify eager fetch of relationships. If 85% of your application use of the customer table involves a reference to their orders, then you may specify that the orders are retrieved automatically.

4. ORMS can do caching. If a set of objects (database items) are frequently queried from the database, some or all of them can be stored in a Java object cache and provided to code from the cache. This also reduces database round trips.

5. Hibernate provides support for natural primary keys or surrogate keys in its database mappings, custom SQL queries for inserts, updates, and deletes, and an Hibernate Query Language (HQL) and Criteria API to generate SQL queries programmatically. It also works just fine with stored procedures and database views.

6. Any database query passing through Hibernate that uses the native Hibernate class loading, the Criteria API, or HQL, or the optional (but strongly recommended) Hibernate utilities for SQL queries has safeguards against SQL Injection attacks. A user can use raw SQL queries without Hibernate tools and permit SQL Injection that way. The Hibernate SQL utilities also use named parameters. So you can do select * from student where first_name = :name. This is better than the Java standard of using question marks, because if you change the order of the parameter items in the query you have to revise the order of the corresponding input values. If you change the order of your named parameters, you don't have to change the order of your input values.

7. Hibernate easily supports database connection pooling, which helps performance considerably.

8.  Hibernate allows us to use a relational database in object-oriented ways.   For instance, say the customer table has an address with all typical address information, and the supplier table has an address with the same information.  In our Java code we use one Java class 'Address' for both uses, and we can map that class to the corresponding columns in the customer and supplier tables.   We can also use polymorphism in our code.   Say we have Guns, Cannons, and Rocket Launchers in our code as subclasses of Weapon, and Guns, Cannons, and Rocket Launcher each have their own database table.   We can save a Weapon, and depending upon the instance the appropriate database table is modified or populated.

9.  Hibernate has dirty-checking.  Say we load an object to the database.  If we don't change it, nothing happens.  If we flush our Hibernate session and it has changed, the changes are automatically written to the database for us.

10. Naturally Hibernate is free to use, because it's open source. It's also rock solid, widely supported, and very well documented. I have the Hibernate In Action book written by two of the lead Hibernate developers (I believe one is the Hibernate founder, I don't remember at the moment), and it's very well written and straightforward to understand.   That's especially impressive considering the source material.

Future post: my criticisms of Hibernate.

No comments:

Post a Comment