Object relational mapping
As the previous discussion shows, we are looking for a solution that enables applications to work with the object representation of the data in database tables, rather than dealing directly with that data. This approach isolates the business logic from any relational issues that might arise in the persistence layer. The strategy to carry out this isolation is generally called object/relational mapping (O/R Mapping, or simply ORM).
A broad range of ORM solutions have been developed. At the basic level, each ORM framework maps entity objects to JDBC statement parameters when the objects are persisted, and maps the JDBC query results back to the object representation when they are retrieved. Developers typically implement this framework approach when they use pure JDBC. Furthermore, ORM frameworks often provide more sophisticated object mappings, such as the mapping of inheritance hierarchy and object association, lazy loading, and caching of the persistent objects. Caching enables ORM frameworks to hold repeatedly fetched data in memory, instead of being fetched from the database in the next requests, causing deficiencies and delayed responses, the objects are returned to the application from memory. Lazy loading, another great feature of ORM frameworks, allows an object to be loaded without initializing its associated objects until these objects are accessed.
ORM frameworks usually use mapping definitions, such as metadata, XML files, or Java annotations, to determine how each class and its persistent fields should be mapped onto database tables and columns. These frameworks are usually configured declaratively, which allows the production of more flexible code.
Many ORM solutions provide an object query language, which allows querying the persistent objects in an object-oriented form, rather than working directly with tables and columns through SQL. This behavior allows the application to be more isolated from the database properties.
Hibernate as an O/R Mapping solution
For a long time, Hibernate has been the most popular persistence framework in the Java community. Hibernate aims to overcome the already mentioned impedance mismatch between object-oriented applications and relational databases.
With Hibernate, we can treat the database as an object-oriented store, thereby eliminating mapping of the object-oriented and relational environments. Hibernate is a mediator that connects the object-oriented environment to the relational environment. It provides persistence services for an application by performing all of the required operations in the communication between the object-oriented and relational environments. Storing, updating, removing, and loading can be done regardless of the objects persistent form. In addition, Hibernate increases the application's effectiveness and performance, makes the code less verbose, and allows the code to be more focused on business rules than persistence logic. The following screenshot depicts Hibernates role in persistence:
Hibernate fully supports object orientation, meaning all aspects of objects, such as association and inheritance, are properly persisted. Hibernate can also persist object navigation, that is, how an object is navigable through its associated objects. It caches data that is fetched repeatedly and provides lazy loading, which notably enhances database performance. As you will see, Hibernate provides caches in two levels: first-level built-in, and second-level pluggable cache strategies. Th e first-level cache is a required property for any ORM to preserve object consistency. It guaranties that the application always works with consistent objects. This is originated from the fact that many threads in the application use the ORM to persist the objects which might potentially be associated to the same table rows in the database. The following screenshot depicts the role of a cache when using Hibernate:
Hibernate provides its own query language, which is Hibernate Query Language (HQL). At runtime, HQL expressions are transformed to their corresponding SQL statements, based on the database used. Because databases may use different versions of SQL and may expose different features, Hibernate presents a new concept, called an SQL dialect, t o distinguish how databases differ. Furthermore, Hibernate allows SQL expressions to be used either declaratively or programmatically, which is useful in specific situations when Hibernate does not satisfy application persistence requirements.
Hibernate keeps track of object changes through snapshot comparisons to prevent unnecessary updating.
Other O/R Mapping solutions
Although Hibernate is the most popular persistence framework, many other frameworks do exist. Some of these are explained as follows:
- Enterprise JavaBeans (EJB): It is a standard J2EE (J ava 2 Enterprise Edition) technology that defines a different type of persistence by presenting entity beans. Mostly, for declarative middleware services that are provided by the application server, such as transactions, EJB may be preferred for architecture. However, due to its complexity, nontransparent persistence, and need for a container (all of which make it difficult to implement, test, and maintain), EJB is less often used than other persistence frameworks.
- iBatis SQL Map: It is a result set–mapping framework which works at the SQL level, allowing SQL string definitions with parameter placeholders in XML files. At runtime, the placeholders are filled with runtime values, either from simple parameter objects, JavaBeans properties, or a parameter map. To their advantage, SQL maps allow SQL to be fully customized for a specific database. To their disadvantage, however, these maps do not provide an abstraction from the specific features of the target database.
- Java Data Objects (JDO): It is a specification for general object persistence in any kind of data store, including relational databases and object-oriented databases. Most JDO implementations support using metadata mapping definitions. JDO provides its own query language, JDOQL, and its own strategy for change detection.
- TopLink: It provides a visual mapping editor (Mapping Workbench) and offers a particularly wide range of object, relational mappings, including a complete set of direct and relational mappings, object-to-XML mappings, and JAXB (Java API for XML Binding) support. TopLink provides a rich query framework that supports an object-oriented expression framework, EJB QL, SQL, and stored procedures. It can be used in either a JSE or a JEE environment.
Hibernate designers has borrowed many Hibernate concepts and useful features from its ancestors
Hibernate versus other frameworks
Unlike the frameworks just mentioned, Hibernate is easy to learn, simple to use, comprehensive, and (unlike EJB) does not need an application server. Hibernate is well documented, and many resources are available for it. Downloaded more than three million times, Hibernate is used in many applications around the world. To use Hibernate, you need only J2SE 1.2 or later, and it can be used in stand-alone or distributed applications.
The current version of Hibernate is 3, but the usage and configuration of this version are very similar to version 2. Most of the changes in Hibernate 3 are compatible with Hibernate 2.
Hibernate solves many of the problems of mapping objects to a relational environment, isolating the application from getting involved in many persistence issues. Keep in mind that Hibernate is not a replacement for JDBC. Rather, it can be thought of as a tool that connects to the database through JDBC and presents an object-oriented, application-level view of the database.
The following screenshot depicts the main participants in the Hibernate architecture:
As the screenshot shows, the main players are Hibernate configuration file(s), mapping definitions, and persistent objects. At the heart of Hibernate is its configuration. This configuration is always presented by an XML, or a properties file and includes the relevant database information, such as database username, password, URL, driver class, and SQL dialect that Hibernate needs for connecting to the database, communicating with it, and performing persistence operations.
Persistent objects form another part of the Hibernate architecture. These objects are what we will persist in the database. These entity objects and their classes, do not need to exhibit any special behavior, except that they must follow some POJO rules.
In addition to the Hibernate configuration file and the persistent objects, Hibernate's architecture uses other XML documents, which define how application objects should be mapped to database tables. These documents specify the respective table of each entity class, the mapping of each class's field to its respective table column, and sometimes other mapping information, such as object associations and inheritance. These files have a simple syntax, making them easy to develop and maintain. However, some utility tools that ship with Hibernate let you automatically generate the mapping files, based on the application classes or database schema, and also allow you to modify them in a graphic tool.
Although these objects are the main players in the Hibernate architecture, a Hibernate application's runtime architecture is not limited to them. The most significant runtime objects are Configuration, SessionFactory, Session, and Transaction.
Hibernate can be used as simply as follows to store or retrieve a Student object:
Configuraion cfg = new Configuration();
SessionFactory sessionFactory = cfg.buildSessionFactory();
Student student = ...//a new instantiated student object
Session session = sessionFactory.openSession();
Transaction tx = session.beginTransaction();
Here, we have just configured Hibernate, started a transaction, stored the student object, committed the transaction, and finally disconnected from Hibernate. These are actually the required operations to interact with Hibernate. The configuration includes setting up Hibernate to work with a particular database with special behavior. Every Hibernate interaction should be done inside a transaction, which justifies the next step.
What is Spring
Now that you've read a bit about Hibernate's background, it is time to look at Spring and what it has to offer.
Spring is an ambitious framework that aims to be a complete solution for entire JEE applications. Unlike Hibernate, which works merely on the persistence tier, Spring is a multitier framework which offers a wide range of services. It makes JEE development easier, by providing a clean separation of concerns, decoupling an application's components, and minimizing complexities typically encountered in sophisticated JEE environments.
Choosing an appropriate solution for a Java application, particularly when it is built with open-source tools, is a common challenge in application design. This is another challenge that Spring aims to address. The challenge starts when you encounter a large number of open-source technologies that may be used for the same purpose, such as Struts, WebWork, JSF, or Tapestry for web, and Hibernate, JDO, and iBatis for the persistence tier. Spring lets you use a large variety of open-source tools behind the scenes, without needing large amounts of code or coupling the application too closely to the underlying frameworks.
Spring is also called a lightweight framework, since it replaces frameworks that are restrictive and cumbersome to use, such as EJB, that are already offered by JEE.
Spring is modularized with several components. Each component provides a particular service. The following sections summarize some of these.
Inversion of Control container
Inversion of Control (IoC) is the technology most identified with Spring. With the IoC core container, Spring enables the management of object dependencies by pushing dependencies into objects at runtime, instead of letting the objects pull their dependencies from their environment. This approach has many advantages:
- All application classes are designed as simple as possible with minimum behaviors, and with their only required properties they will be well documented.
- All application classes are self-documented, and the documentation is always up-to-date.
- No class has its own configuration management, which allows more manageable code.
- The application leaves configuration management to the framework.
- IoC increases consistency in configuration management, since such management is accomplished by the framework.
- The application has no need for any configuration management code since the framework handles this common aspect of every application.
Aspect-oriented programming framework
Aspect-oriented programming (AOP) is the perfect complementary approach to IoC, solving common problems related to J2EE design. AOP allows us to consolidate functionality, which would be otherwise scattered in different places, in a single place. Managing transactions is an example of this functionality. With Spring, transaction management occurs in a single place and is not scattered in persistence methods.
AOP complements object-oriented programming (OOP) by introducing a new concept, called concerns or aspects, to model real-world objects. Concerns are processes that are not directly related to the object hierarchy. Instead, they spread over sets of operations. For example, logging, security, and transaction are common examples for a concern, since they should be applied to sets of methods without any relationship to the object hierarchy.
Spring AOP has the following key benefits:
- I t prevents code duplication and provides more manageable code.
- It allows declarative enabling or disabling concerns.
Data access abstraction
Spring allows consistent data access to be implemented with solid abstraction. This is carried out through a rich hierarchy of exceptions and a set of helper classes, for working with a wide range of persistence technologies.
Spring provides a transaction abstraction lay er over JTA (Jav a Transaction API) global transactions, which span multiple transactional resources. They are managed by an application server, or local transactions managed by JDBC, Hibernate, JDO, or any other persistence technology. It allows coding transactions, either programmatically or declaratively.
MVC web framework
Spring provides a rich, powerful web framework based on the Model-View-Controller (MVC) pattern. The aim of the framework, like any other web framework, is to simplify web development. It allows a variety of different view technologies, such as JavaServer Pages, Velocity, and iText PDF to be used. You can use MVC with Spring's other services, such as AOP and IoC. Furthermore, Spring can be integrated with other web frameworks, including Struts, WebWork, Tapestry, and JSF. Discussing Spring's web framework is beyond this article's scope. However, we will take a quick look at it, along with its alternatives, to give you a sense of how, in practice, Spring can be used to make web development easier and solve typical problems related to web applications.
Spring applications are more readily testable than other applications. This is because Spring applications rely on POJOs, which do not call any Spring APIs, and their dependencies are normally expressed in the form of interfaces that are easy to stub or mock. Moreover, Spring provides some useful helper classes for implementing test classes that test an application's interaction with Spring.
Moreover, Spring provides a lightweight container against traditional full-blown JEE containers. The container provided by Spring can easily be started from the JUnit test itself, which is not easy to do with EJB-3 and a JEE container.
This article looked at Hibernate's background and explored how the framework provides a bridge between the object-oriented and relational worlds. This is why Hibernate is called an O/R mapping tool.
Enterprise JavaBeans are server-side components which provide another approach to persisting Java objects. In addition, enterprise beans provide declarative middleware services, such as transaction and security. Developing with enterprise beans is not as easy as developing with Hibernate, and using entity beans also requires an application server, which is difficult to set up, run, and test.
Hibernate architecture consists of three contributors: persistent objects, configuration file(s), and mapping definitions. The Hibernate API comes with three Java interfaces which are always involved in persisting the objects. These are org.hibernate.Session, org.hibernate.SessionFactory, and org.hibernate.Transaction.
If you have read this article you may be interested to view :