Friday 20 June 2014

Hibernate_1_Basic Application

There are billions of pages of information on web related to any topic. This one will make difference among all.

Targeted Audience : Average Java Developer
Pre-requisites : Core Java, Minimal RDBMS concepts, Know what JDBC does.

Project Structure for application





































package com.ntt.pojo;


/*
This is a simple POJO class
We can see only three variables defined related to a Typical Account.We have used the toString() method of the class. This is useful to print the values for the variables we have used without much trouble. 




*/
public class Account {
    private int accNum;
    private String name;
    private double balance;
    @Override
    public String toString() {
        return "Account [accNum=" + accNum + ", name=" + 

name + ", balance="
                + balance + "]";
    }
//Getters and setters for the variables.
    public int getAccNum() {
        return accNum;
    }

    public void setAccNum(int accNum) {
        this.accNum = accNum;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getBalance() {
        return balance;
    }

    public void setBalance(double balance) {
        this.balance = balance;
    }

}

Account.hbm.xml

<!DOCTYPE hibernate-mapping PUBLIC
   "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
    <class name="com.ntt.pojo.Account" table="Account">
        <id name="accNum" column="accNumber">
        </id>
        <property name="name"
column="accNumber">
        </property>
        <property name="balance" l />
    </class>
</hibernate-mapping>
<!--


Explanation about this file

1. Using this file we are telling Hibernate to Map the POJO class to the Database table. In order to achieve this, we need to use the tags as specified or as understood by the Hibernate. Following are the tags we have used.


<class> tag


Using this tag we will be telling Hibernate that there is a POJO class with name 'Account' and which is related to the database table 'Account'

For simplicity sake, we will use both, POJO Class and Database Table names same. 

<id> tag

This tag is crucial one. Before understanding this tag, we need to know what is primary key of a database table. 

We know that Primary key of database table is important one, which will identify a unique row amongst the given rows. Or for a layman to understand consider following case. 

Suppose, there are 100 employees in an organisation. Given this case, we know that there will be few employees having exactly same names, ages, or any other parameter/property of employee. 

In such cases, what is the parameter or property of employee, using which we can pull out only one (unique). Possibly, we end up combination of various properties to do so. This might lead to cumbersome experience.

In order to tackle such situations, we use an extra property for the table. This property we assume and keep as unique for entire column. 

That unique key property must also be available in our POJO class. 

Always remember that, [database table] representation and [java world ]representation are NOT(R) NOT SAME.

This tag takes good number of attributes. One of such is 'name'
This attribute takes a value that must be same as the 'property' name given in the pojo class. 

Note that we have used 'accNum' here and we can find same in the Account Pojo class.

Next attribute we can see is Column. This relates to the database table column name. Again, this must (r) must match with the name given in the database table. 

For now this is enough. 

Note : As said, this is very important tag for Hibernate and hence made as mandatory tag for mapping a POJO class and Database Table.

<property> tag

This tag is used to map the properties used in the pojo classes.
This tag takes a name attribute  which takes the value just same as the property name mentioned in the POJO class.




-->

hibernate.cfg.xml



<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>


<session-factory>
  <property name="hibernate.dialect"> 
     org.hibernate.dialect.OracleDialect
 </property>
 <property name="hibernate.connection.driver_class">
     oracle.jdbc.OracleDriver
 </property> 
 <property name="hibernate.connection.url">
     jdbc:oracle:thin:@localhost:1521:xe
 </property>
 <property name="hibernate.connection.username">
     hibernate
</property>
<property name="hibernate.connection.password">
     hibernate
</property>
<property name="hibernate.show_sql">
     true
</property>
<property name="hibernate.hbm2ddl.auto">
    create
</property>

<mapping resource="Account.hbm.xml" />

</session-factory>

</hibernate-configuration>
<!--

Explanation about the configuration file

This is the most important file in the Hibernate Based applications.
Lets understand tags used in the xml file. 


<hibernate-configuration> tag

This is the base tag for the configuration file. Hibernate starts reading the contents inside this tag. Hibernate uses the DTD specified above so as to match the tags that are encountered ahead. 
As the name of the tag suggests, this basically houses or encapsulates the Configuration Details required by Hibernate.


<session-factory>

This tag is succeeds the <hibernate-configuration> tag.
This tag in turn contains other important tags which capture various details.
Inside this tag, we use various properties related to the SessionFactory.
Each such property is defined and a value is assigned using <property> tag


<property name="hibernate.dialect"> 
     org.hibernate.dialect.OracleDialect
</property>

This is crucial property of entire configuration file.
We know that Hibernate is ORM tool or software or technology.
Means, Hibernate bridges the mismatches that existing between the Object world (i.e. Java) and Relational world (i.e. Database)

We know that there are many databases and each one has its own style of syntax.

So, Hibernate has provided a property to specify which database we are using in advance. Typically the Database name is prefixed to the word 'Dialect'

Here I have used Oracle10gXE as my database, hence, telling that please use the [OracleDialect] for my database operations. 

Why we need to specify?

This is required because, when ever we use Hibernate based Database operations, internally, Hibernate consults this dialect and converts the Hibernate based queries to the database which we specified.


<property name="hibernate.connection.driver_class">
     oracle.jdbc.OracleDriver
 </property> 

This is the Connection Provider property settings. Here we are using the OracleDriver which supplied in ojdbc14.jar
 


 <property name="hibernate.connection.url">
     jdbc:oracle:thin:@localhost:1521:xe
 </property>

This is the location of Database installed. Typically, as we can see, we will provide the [TYPE OF DRIVER][IP Address : Port : SID name]

 <property name="hibernate.connection.username">
     hibernate
</property>
<property name="hibernate.connection.password">
     hibernate
</property>

These two properties relate to the Logical Dataabse / User Name inside the Oracle Database. We need to understand that, Oracle is a software or server, which can host multiple [logical] databases that are identified with they words [user / schema].

Here, I have created a [user] with the name [hibernate] and password [hibernate]

Hibernate will uses these credentials to access the database.


<property name="hibernate.show_sql">
     true
</property>

This property is very useful while developement. 
We know that our application will be interacting with the database many number of times. And each time it interacts, Hibernate will generate SQL statements. These statements can be see on the console, when we enable this property. 

'True' indicates, the statements are shown on the console or written to log file.
'False' indicate the opposite. 

<property name="hibernate.hbm2ddl.auto">
    create
</property>


This is most dangerous tag in the configuration file


This another important property of the configuration file.
hbm2ddl means [hibernate mappings to data definition language].

Suppose, we are creating an application from scratch and there are no database tables existing. And we have identified various POJOs that are required in the Application.

Using this tag, we can tell Hibernate to create the tables dynamically for us. This property takes any of the following values.
  • validate: validate the schema, makes no changes to the database.
  • update: update the schema.
  • create: creates the schema, destroying previous data.
  • create-drop: drop the schema at the end of the session.
We typically use only [update] or [create] or we do not use at all in the real world applications.

When we use [create] hibernate will create all the tables that are mapped with Hibernate Settings i.e. in Hibernate Mapping Files.

This is useful when we have lot of dependencies and constraints in the hierarchy. Hibernate will manage everything while creating the new tables and their hierarchy. This includes, primary key, data types, length, foreign key constraints, indexes, etc.

When we use [update] hibernate will  simply update the missing things.



-->

Test.java
 
package com.ntt.client;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
import com.ntt.pojo.Account;
public class Test {
    public static void main(String[] args) {





     Configuration cfg = new Configuration();





/*

For any Hibernate based application to start, we need to instantiate this object. 
*/
     cfg.configure("hibernate.cfg.xml");


/*
Using the configuration Object we are telling Hibernate to configure. This method, as we can see take String as parameter. We need to supply the 'hibernate configuration file' that we have created.Hibernate will load all the related configurations using this file.

Important: We will configure one configuration for a single database. If we require mulitple databases in our application, we need multiple configuration objects 
*/
        SessionFactory factory = cfg.buildSessionFactory(); 

/*

This is the interface which holds all the configuration data. As the name of the interface suggests, it is a Factory for Session Objs. When we say [cfg.buildSessionFactory()], Hibernate will return an object  of SessionFactory. Using this object we can obtain Hibernate Session. Note that this SessionFactory is a heavy weight Object. Means, frequent creation of this Object will lead to performance issues. Hence, it is advised to create only one SessionFactory for entire app.
*/
        Session session= factory.openSession();

/*

Using the SessionFactory we will obtain a Session. This is light weight object, and can be created as many number of times as required and closed.  This object contains various methods, which help us to perform the database related operations.
  */


        Transaction t = session.beginTransaction();
/*
Before we go for this line, we need to know what is 'commit' in database terms.While performing a database operation, particularly DML operations, database will never make the action performed as persistent or final when executing. 

All the execution is performed [in-memory]
Actual data is never affected. 

Then when it is affected?
There is a command [commit] in database, when we use this line, then only all the DML operations are made permanent. 

Taking cue from above few lines, it is a good practice to put our DML operations as part of Single Transaction. Subsequently, when we know that these operation are good to go, we use the Commit operation. 

As part of such theory, Hibernate provided Transaction object.

Any DML queries need to be between this line and commit line.

*/
        Account a = new Account();
        a.setAccNum(1);
        a.setBalance(10000);
        a.setName("Santa");


/*
Above few lines creates Object of Account with the properties being set with the values mentioned.  
*/
       
session.save(a);
/*
Then we use a method called [save()] of session object to make the object persistent. 
Note that in order to make these values persistent in pure jdbc, we would have used following few lines. 
Class.forName("oracle.jdbc.driver.OracleDriver");
con = DriverManager.getConnection(
                    "jdbc:oracle:thin:@localhost:1521:xe", "hibernate", "
hibernate");

String query = "insert into account(accNum,name, balance) values(?,?,?)";
ps = con.prepareStatement(query);
ps.setInt(1, 1);
ps.setString(2, "Santa");
ps.setInt(3, 10000);
count = ps.executeUpdate();


All these lines are reduced to single line and that to in Object Oriented Fashion. Most of the developers like this reduction of work.

Note that this kind of approach is very useful. Because, suppose a property is removed from the Table and Class, then we need to change the query here. This becomes very cumbersome exercises, if this query is used at multiple places.


*/
        t.commit();
/*

When we use this line, Hibernate will actually persist the object into the database. We can see an 'insert' sql statement being fired in the console. 
*/
       
session.close(); 
}


}
 
/*
Text with this background is Actual Code  
Text with this back ground is comment about the code
*/