Before the advent of Hibernate, there were so many other technologies and specifications from Sun, for persistence. Few are them are explained in detail in the following sections along with their drawbacks which led them not being able to become a successful one.
Problems with JDBC
Java provided an initial solution for persistence in the form of JDBC and developers are depending on JDBC API’s to connect to the database. One of the major drawbacks of JDBC is that, one has to embed the application’s data into the SQL syntax, i.e., for saving the data in an application, the business object has to be converted to relational-object model by embedding the various pieces of data within the SQL language syntax.
Consider the following situation, there is a business object called Employee with properties name and age and this has to be persisted to a database. The following is the class representation of the Employee class,
class Employee
{
private String name;
private int age;
//Other Methods go here.
}
Employee employee = getEmployeeObject();
String sqlInsertStmt = “INSERT INTO EMPLOYEE VALUES (’” + employee.getName() + “‘, ‘” +
employee.getAge() + “‘)”);
statement.executeQuery(sqlInsertStmt);
The above is generally a poorer code, and also the business object (Employee object, in our case) is tightly integrated with the SQL syntax.
During data retrieval, the reverse of the above process will happen. The information that is fetched from the database has to be mapped to the business object. Consider the following piece of code which has the conversion process of representing the business object from the relational data model.
String sqlQueryStmt = “SELECT * FROM EMPLOYEE WHERE EMP_ID = ‘100′”);
ResultSet employees = statement.executeQuery(sqlInsertStmt);
if (employees.next())
{
Employee fetchedEmployee = new Employee();
fetchedEmployee.setName(employees.getString(”name”));
fetchedEmployee.setAge(employees.getInt(”age”));
}
Entity Beans
Entity beans, which were one of the major components in the EJB Specification failed drastically to provide a persistent layer in the applications.
The initial version of the EJB specification has little support for the Entity beans. The first disadvantage is, an Entity Bean is not a local object, but a remote object, so, there are overheads related to network performance issues. And the worst thing is that the relationships between entity beans have to be manually managed in the application code and the actual mappings were done in vendor-specific configuration files which invented lots of changes in the configuration files when the application is made to point out to a different database server.
Though, the later version of the specification overcome many of the drawbacks that were found in the initial versions by introducing the notion of local interfaces for representing an enterprise bean and EJB Query Language (EJB-QL), etc., the art of designing and managing an entity bean still yielded much complexity in the hands of the developers.
Hibernate – ORM product
Hibernate is one of the Object-Relational Mapping software for persisting and querying data. Most of the Hibernate features look very similar that are found in “Java Persistence API (JPA)” specification. Also Hibernate provides some add-on functionalities that are not mentioned in the JPA specification. Hibernate doesn’t replace JDBC. Hibernate is sitting on top of JDBC to connect to the database. Internally Hibernate is using these JDBC calls to connect to the database systems.
Hibernate is neither forcing its developers to use some specific interfaces for the classes to be persisted in an application nor it requires the program to follow some standard design to achieve its goals. For this reason, Hibernate can well integrate with all kinds any of J2SE/J2EE application and with any kind of frameworks (like Spring, Struts etc).
Hibernate Modules
The open-source Hibernate project has various different modules each representing a unique functionality.
* Hibernate Core which represent the basic and the core module of the Hibernate project provides support for OO features along with the Query services.
* Another module called Java Persistence with Hibernate is an implementation for the specification “Java Persistence API (JPA)” from Sun and we can be used in any Sun’s compliant Application Server as well as with J2SE applications.
* There is a separate module called Hibernate Search that provides rich functionality for searching the persistence domain model using a simplified API.
* For validating the data, Hibernate comes with a set of validation rules in the form of Annotations in a module called Hibernate validations and it also allows the developers to create custom validation rules.
* Support for Querying and inserting data from multiple databases can be achieved by using the Hibernate Shards API.
Hibernate Core API
Following section covers the various core interfaces/classes that should be used by an application which is depending on the persistence-level service from Hibernate.
The ‘Configuration’ class
The Configuration class is the initial entry point of a Hibernate application. An instance of Configuration class represents application specific configuration that provides persistence services. This class provides convinient ways to import the Hibernate Configuration File and the necessary Mapping Files (which are discussed later) into an application which can be later used by SessionFactory (which is detailed in the next section) class to create Session objects.
The following code shows how to create and configure a Configuration object.
Configuration configuration = new Configuration().configure();
Calling the Configuration.configure() method will configure the object by loading the configuration file and the mapping files that are available in the application’s class-path.
Usually only one instance of a Configuration class will be maintained by an application.
The ‘SessionFactory’ interface
The Configuration class can be used to create SessionFactory object which serves as a factory class that creates Session objects (discussed in the next section). An application may have one SessionFactory class but many number of Session objects. The following code shows how to create a SessionFactory object by calling the Configuration.buildSessionFactory().
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Configuration.buildSessionFactory() will create a new SessionFactory object with configurations and the mapping information taken from the Hibernate Configuration and the Mapping Files.
The ‘Session’ interface
A Hibernate Session interface forms the primary interface for promoting persistence services to the application classes. The following code shows how to create a Session object.
Configuration configuration = new Configuration().configure();
SessionFactory sessionFactory = configuration.buildSessionFactory();
Session newSession = sessionFactory.openSession();
Calling the SessionFactory.openSession() method, will create a new database connection (the connection related information like the Database server, username, password etc., will be taken the Hibernate configuration files which is discussed in the later section) and opens a new session from the created connection. Calling the SessionFactory.openSession() method again will create new Session objects as well as new java.sql.Connection object. One can get a reference to the newly created connection by calling the Session.connection() method, like the following,
java.sql.Connection connection = session.connection();
Object Classification based on States
Three different types of objects are categorized in Hibernate technology based on the state of the object. They are,
# Persistent Object
# Transient Object
# Detached Object
Persistent Object:
A persistent object is one which is associated with the current Session and has its state values synchronized with the database.
Transient Object:
A transient object doesn’t have any association with the current Session, but can be made persistent at a later time.
Detached Object:
A detached object was having an association at a previous point of time with the Session interface, but now is made to detach (taken-off) from the current Session.
Operations using the Session Interface
As seen previously, the Session interface provides various services in the form of operations for persisting any Object. It also provides transactional services to the persistent objects. Rich Querying operations are also supported in the form of Query interface. The following code can be used to persist an object.
Employee objectToBePersisted = new Employee();
// Set properties for employee object here.
Session session = …;
session.save(objectToBePersisted);
Session.save(object) can be used to save a persistent object along with a unique key (primary key). Calling the method again on the same object will cause the following exception to be thrown. org.hibernate.exception.ConstraintViolationException. However, calling this method doesn’t immediately synchronize the state of the object with the database. It will just mark this object to be saved. Calling the method Session.flush() will make all the objects that are associated with the Session to be synchronized with the database.
session.flush();
There is a method called Session.update(object) which is used to update the state of the persistent object that was modified for some reasons after a call to Session.save(object). Consider the following code which will demonstrate this,
Employee employee = …;
//Set employee properties here.
session.save(employee);
//Update the properties of employee object here.
employee.set(…);
session.update(employee);
If you don’t like to use Session.save(object) or Session.update(object), use the smart Session.saveOrUpdate(object) method, which will call Session.save(object), if the object in consideration is a new object or will call Session.update(object), if it is an updated (saved) object.
session.saveOrUpdate(employee);
There are so many other useful services and operations available from Session interface like Session.delete(object), Session.merge(object), and Session.refresh(object).
Objects can be retrieved from the Database using the Query interface. The following code resembles the traditional select query to select all the object from a table called User.
Query selectQuery = session.createQuery(”FROM User”);
List userList = selectQuery.list();
for(int index = 0; index < userList.size(); index ++){
User user = (User)userList.get(0);
System.out.println(”Name = ” + user.getName() + “, Age = ” + user.getAge());
}