Tuesday, April 18, 2006

[itsdifferent] HIBERNATE

Hibernate is an ORM (Object Relational Mapping) technology. It is an Open Source and free technology, developed in SourceForge.net. There have been a number of such ORM technologies in the recent past. TopLink is one such tool, subsequently adopted by Oracle and so is now proprietary.

 

Hibernate from SourceForge and OJB (Object Relational Bridge) from Apache are two well-known ORM tools, Open Source and free. JDO also falls within the same category.

 

Gavin King is the lead developer of Hibernate while Craig Russell and David Jordan are the lead authors for the SUN-sponsored JDO effort. Owing to some technical problems, it appears that the majority in JCP favours Hibernate today instead of JDO. At first reading though, the difference is not all that apparent. The syntax and approach appear to be almost alike, but Hibernate syntax is easier to learn.

 

It is interesting to note that Craig Russell works for SUN and Gavin King is now with JBoss. It shows that JCP is a democratic community and SUN is not dictating terms, except to protect the language and its enterprise-level users.

 

EJB-3 is the latest version and is heavily influenced by Hibernate. Some readers equate EJB-3 with Hibernate while a few others compare EJB-3 to JBOSS! Oracle supports EJB-3 proposals and as it is the main database company in the J2EE world, EJB-3 has a bright future. J2EE (Java 2 Platform, Enterprise Edition) by its very name is an enterprise level technology, and as EJB is the essence of such enterprise applications, because of the built-in container services offered, the significance of the surging interest in Hibernate can be really appreciated only in association with EJB and hence a detour into EJB is inevitable.

 

EJB is of three types. One type is the SESSION BEAN, residing in ENTERPRISE container, which can be thought of as a function bean, invoked in RMI-IIOP style (this is a rough definition). Such a session bean may either be stateless or stateful. This type of EJB has stood the test of time during the last six years and even gained wide approval, including for data-access, since it fits very well with the emerging XML Web Service technology, and is very easy to learn and implement. (An earlier tutorial on EJB for web service in the February 2005 issue of DeveloperIQ illustrates this feature). The stateless bean working in Enterprise container has an exact counterpart in Microsoft COM+(MTS). However, the other types are said to be available in MS platform only through third-party extensions.

 

ORM tools have been sometimes used along with Session beans. The only problem till recently was that they were proprietary and rather costly. However, nowadays, very reliable Open Source ORM tools are available and even Richard Monson-Haefel (an acknowledged authority and author on EJB) approves this method as a safe and productive alternative to Entity beans (page no. 467, EJB by Haefel-OReilly).

 

The other branch, ENTITY BEAN has been less lucky. EJB-1.1, EJB-2.0 and then EJB-2.1, have meant a number of changes in the specification relating to Entity Beans.

 

We can say that an Entity bean is an “Attribute bean” or “property bean”, with setter and getter methods, invoked in RMI-IIOP style and persisted in Enterprise container. The pattern of defining a typical Javabean is a recurring theme in Java. The same style occurs in BDK, EJB-Entity beans, Struts, JSF and now in Hibernate too. So, it is very important and elegant.

 

The third form is messaging paradigm and Message-Driven bean (MDB). A recent article in the web dubbed the ‘RPC’ style, on which the previous two types of EJB are based, as stone-age technologies! An Enterprise by its very name implies a huge number of customers and concurrent transactions; RPC style being like a telephone call could result in “line-engaged” problem! If the call involves the called person referring to some records before replying, it leads to line- blocking. However, messaging style, as in email, at least ensures that the message has been sent. It is evident that dubbing RPC (read ‘telephone’) as unsuitable is an overstatement. Sometimes, we desire immediate response, too. By the same token, even XML web service, if it is really serious, should adopt messaging style and it does. MDB has weathered the storm and is in fact gaining more and more acceptance.

 

So, why is it that Entity beans alone was found wanting and the specification keeps on changing?

 

Entity beans are of two types – CMP and BMP. CMP stands for Container-Managed Persistence and BMP stands for Bean-Managed Persistence. Theoretically, the EJB specification does not say anything about the method to be adopted in persisting objects for permanent storage and retrieval. It could be simple object serialization. The database may be an object database or Object-relational database or XML. In practice, however, a database has always meant a Relational Database and its SQL.

 

In a very complex Enterprise application, we begin with Modeling. Instead of dealing with tables and their complex interrelations, it is more intuitive to deal with classes and objects. Thus we design our system, “thinking in objects” and not in tables. So long as we are dealing with objects in memory or with objects persisted in hard disk simply as objects, there is no problem, except that object serialization, especially of complex objects is a slow process. On the other hand, Relational Database technology is fast, time-tested, well-known and famous. So, the problem is to work with objects in memory but persist the objects in hard disk as relational database.

 

This is what is known as ORM (Object Relational Mapping). If we opt to deal directly with tables only and either read data or manipulate data by session beans, we skip the entire ORM problem. Nevertheless, how practical is it for really complex projects? That is the rationale for the development of Entity Beans in EJB.

 

In CMP, the coder deals with objects, only in memory. He creates new objects, modifies them, deletes them and views them, all in memory. The task of saving these objects in memory to the relational database table is done by the container automatically. The coder does not write any SQL-related code for this.

 

In BMP, the coder has to write the SQL to persist the object in memory to the relational database.

 

CMP in EJB1.1 was suitable for simple tables, without complex relationships to other tables. CMP avoids all references to the underlying database. So, it is more portable. There is no vendor lock-in. CMP can persist data to Object databases also, besides Relational databases.

 

Even so, CMP is not always suitable. If the database is some legacy type, which cannot be used with SQL, the database company gives a proprietary code for persistence and such code has to be used in our program to persist data. The facilities given in CMP originally were found to be too elementary and there were complaints.

 

Nonetheless, what counts is that CMP makes use of ORM concepts, though the implementation left much to be desired. It did not expose how the EJB vendor implements it. Weblogic, Oracle, IBM WebSphere, SUN, JBoss, each may implement CMP in any way that they deem fit. Except in special circumstances, it will be better to use CMP, not merely because it makes the code more portable and is easy to write. A much more important reason is that the EJB container can optimize the performance dramatically, if we adopt CMP. So the developer community wanted to adopt CMP but found it unsuitable for really complex jobs.

 

And a sizable section of developers found the XML Deployment Descriptors for CMP, especially for complex jobs, a bit troublesome and tedious. It can be said that any design that makes us dependent on wizards, is a bad design. Unlike the Deployment Descriptors for Session beans, which can be hand coded in a jiffy, by just find/replace method in a text editor, the DD for CMP required three XML files, two of them very special to the container used.

 

In order to improve things, EJB 2.0 proposed a few changes, mainly in the matter of writing CMP. It provided for Relationships and proposed a simple query language known as EJB-QL. Since, calling an Entity bean through a session bean (Facade pattern) is more efficient, from the viewpoint of minimizing network traffic, the very concept of remote interface for entity beans was questioned and so local interface was also provided for Entity beans. (In a total reversal, there is no local interface in EJB-3 and instead of EJB-QL, Hibernate Query Language is taking over in EJB-3).

 

Even with all these improvements, CMP was found to be less than the ultimate solution. There was no possibility for Inheritance. Though the container services provided by the EJB container are indispensable in a truly large enterprise application, the J2EE camp is almost vertically split into WebTier and EJB-Tier votaries. WebTier supporters claim that EJB, with its steep learning curve and error prone development environment for developers, is not really necessary for most applications. And they would like to have an ORM tool built into the J2EE specification.

 

For after all, ORM task is not specific to EJB alone. Even Servlets and JSP could use them. In fact, they have been using them, though the J2EE specification was silent about it. ORM tools like OJB, JDO and Hibernate can be used not only in EJB containers, but also even in web container and standalone containers. Gavin King makes it a special point in favour of Hibernate. Making such a tool a J2EE standard would make development tasks far easier; to develop either web-tier application or EJB-tier application, saving us from the medley of classpath to required jars.

 

In a scathing attack on the complexity and questionable performance of EJB Entity beans (though, unjustifiably on EJB itself), Rod Johnson, prophesies that in a few years’ time J2EE will cease to include EJB. Whether, we agree or not, it is worth looking into the criticisms against EJB Entity beans, raised by him. (J2EE Development without EJB -Wrox/Wiley/DreamTech-2004). For, he is proposing the Spring Framework as an alternative to EJB container and the idea is gaining ground. J2EE developers and students may have to reorient themselves, rather abruptly, to remain relevant to the industry.

Hybernate2 can be downloaded from www.hibernate.org. We can unzip and install it in any directory of our choice. In our case it is c:\hibernate2. If we look in c:\hibernate2 folder, we will find hibernate2.jar. Besides this, we find a number of jar files in the c:\hibernate2\lib folder. The following important jar files are available:
cglib2.jar,
commons-collections.jar
commons-Logging.jar
dom4j.jar
ehcache.jar
jdbc2.0-stdext.jar
log4j.jar
xerces.jar
xml-apis.jar

 

The hibernate2.jar and all the above jar files have to be placed in our classpath.

 

As mentioned already, hibernate can be used in standalone application, web application or in EJB. This facilitates easy testing without having to deploy either in the web container or EJB-container.

 

So, we will create our working folder as: c:\hiberdemo.

 

In the next step, we can create a setpath.bat file in c:\hiberdemo as:
set path=c:\windows\command;

d:\jdk1.4\bin.


Next, we shall create a setcpath.bat to include c:\hibernate2\hibernate2.jar and similarly all the above-mentioned jar files. This must be carefully typed and checked thoroughly for correctness (it will be pretty lengthy).

 

We CD to c:\hiberdemo and give two commands to set the path and classpath. We have to create four files in c:\hiberdemo:

  1. hibernate.properties (known as hibernate configuration file): This file is used to give details of the database used by us for Hibernate.

  2. We want to create a java class, which will be automatically persisted to Relational Database, by hibernate. This class follows the standard JavaBeans convention. In our example, it is player.java.

  3. We must create a mapping document. This is an XML document, typically, player.hbm.xml

  4. The fourth file is our stand-alone application to test and use hibernate. We can have a simple frame program with four buttons for add, modify, delete and find operations. We can call it hiberframe.

  5. We should have installed the relevant Database software, referred to in the hibernate.properties file.

We can use a number of databases with Hibernate. A typical properties file is given below (this is for MySql database).

c:\hiberdemo\hibernate.properties
hybernate.dialect=
net.sf.hibernate.dialect.MySQLDialect
hibernate.connection.driver_class=
com.mysql.jdbc.Driver
hybernate.connection.url=
jdbc:mysql://localhost/hiberdemo
hibernate.connection.username= 
hibernate.connection.password= 

 

This can also be written as an XML file hibernate.cfg.xml. This is preferred and recommended (either hibernate.properties or hibernate.cfg.xml). Both have the same function.

// hibernate,cfg.xml
<?xml version=”1.0” encoding=”utf-8”?>
<!DOCTYPE hibernate-configuration PUBLIC 
“-//Hibernate/Hibernate Configuration DTD//EN”
“http://hibernate.sourceforge.net/
hibernate-configuration-2.0.dtd”>

<hibernate-configuration>
<session-factory>
<property name=”connection.driver”>
com.mysql.jdbc.Driver 
</property>
<property name=”connection”>
jdbc:mysql://localhost/hiberdemo 
</property>
<property name=”dialect”>
net.sf.hibernate.dialect.MySQLDialect
</property>
</session-factory>
</hibernate-configuration>

 

This file speaks of MySql jdbc driver. We must obtain the software and place it in c:\hibernate2\lib and then include it in our classpath.

 

Next, we create the player.class file as shown below:

// c:\hiberdemo\player.java
public class player
{
private String name;
private String place;
private int id;
public player() { }

public player(String a,String b)
{
name=a;
place=b;
}
public String getName()
{ return name; }
public void setName(String a)
{ name = a; }

public String getPlace()
{ return place; }
public void setPlace(String b)
{ place = b; }

public int getId()
{ return id; }
public void setId(int s)
{ id = s; }

}

 

This is just the usual JavaBean file. We must strictly follow the JavaBean convention. It must have a public no-args constructor. It has another constructor, too.

 

We can easily compile this file to get player.class. This class will be referred to in the mapping document, known by the name player.hbm.xml.

 

// c:\hiberdemo\player.hbm.xml

<?xml version=”1.0”?>
<!DOCTYPE hibernate-mapping PUBLIC 
“-//Hibernate/Hibernate Mapping DTD 2.0//EN”
“http://hibernate.sourceforge.net/hibernate-mapping-2.0.dtd”>

<hibernate-mapping> 
<class name=”player” table=”player”>

<id name=”id” type=”int” 
unsaved-value=”null”>
<column name=”ID” sql-type=”int” 
not-null=”true” />
<generator class=”hilo”/>
</id>

<property name=”name” type=”string”/> <property name=”place” type=”string”/>
</class>
</hibernate-mapping>

 

Having created all these files, we can now write the code for a simple framedemo. (The GUI code is not given here. We need not use Swing. All that we require is a set of four buttons and a text area for displaying the result.

 

The GUI code fragment will be as follows:
As our player class has name and place values, we provide two textboxes for adding new values. The text3 is the criteria for finding. We provide 5 buttons (add, modify, remove, find, showall) and display the message in a textarea. In the constructor,
hiberdemo()
{
...
....

panel1.add(text1);
panel1.add(text2);
panel1.add(text3);

panel2.add(TextArea);

panel3.add(button1); 
..
panel3.add(button5);

 

That takes care of the GUI. We must have the following imports:
import java.io.*;
import java.util.*;
import net.sf.hibernate.*;
import net.sf.hibernate.cfg.*;

 

In the constructor itself, we have to initialize the SessionFactory, using the try-catch block. See code 1.

try

Configuration cfg = 
new Configuration();
cfg.addResource(“player.hbm.xml”);
cfg.setProperties
( System.getProperties() );

SessionFactory factory = 
cfg.buildSessionFactory();

area1.setText(“factory ready”);
}
catch(Exception e1)
{ area1.setText(“”+e1); }

 

The code creates a new configuration object and tries to load the mapping document for the class specified in the addClass() method. Here, the code attempts to find the file named player.hbm.xml.

 

To build a Session object, a session factory object needs to be instantiated from the Configuration object. The constructor assumes there is a class attribute defined as:
                factory =null;

 

The buildSessionFactory() method builds a factory based on the specifics of mapping document processed by Configuration object.

 

After thus initializing, we can write code snippets for add, modify, delete and find. The code for adding is (code 2):

String a = text1.getText();// name 
String b = text2.getText();// place

try
{
Session session = 
factory.openSession();

Transaction tx = null;
tx = session.beginTransaction();

player player1 = new player(a,b);
session.save(player1);
tx.commit(); 

session.flush();
session.close();
area1.setText(“added”);
}
catch(Exception e1) 
{area1.setText(“”+e1);}

 

The above steps are very easy to comprehend. A new object is created in memory with the given ‘name’ and ‘place’ and is persisted in the player table. The required SQL is automatically generated by Hibernate and carried out. The id is automatically created by ‘hilo’ generator.

 

The Session object handles all the work involved in saving, updating and loading objects from permanent storage. A Session should be invoked for a short time, to save or load an object. One of the most important actions performed by the Session object is creating a connection to the database. The session object includes the methods save(), update() and saveOrUpdate().
Thus, for creating either add or update or delete or find operation, we first create the session object:
               
Session session=factory.openSession();

 

Then we begin the transaction. After either creating a new object or getting a reference to the required object, we perform the operation. For adding,
session.save(player1);
For updating,
player1.setName(“....”);
player1.setPlace(“....”); 
as required and then,
session.update();

 

Finally, for deleting, get a reference to the object to be deleted and give the command:
               
session.delete(player1);

If we want to find an object by its id, we can use,
               
session.find(player.class, id);

 

It is always better to carry out all these operations within a transaction. James Eliot in ‘Hibernate -A developer’s notebook’ (OReilly) reports that he found that persistence was not done well without transaction (Page no. 46).

 

The following code section will also occur for each operation.
tx.commit(); 
session.flush();
session.close();

 

Hibernate can persist objects with complex attributes like collections and other objects. It supports very involved relationships and also provides its own simple query language, known as HQL. We have Query objects too. There are something known as Criteria queries. Advanced features like Hibernate Annotations have been developed.

 

Regards,
Deven Goratela
देवेन गोरातेला



Note: This Group is not a Job Searching Group, so please co-operate and dont transfer any kind of job related material across this Group.AnyOne doing so can be banned from the Group
Thanx , Group Co-Ordinators




YAHOO! GROUPS LINKS




No comments: