Sunday 20 December 2015

Hibernate Overview

Persistence:

In core Java

Persistence implies, using Serializable interface to permanently store object on the Hard Disk

In Enterprise Application

Using JDBC API to store data permanently in database
      Process of storing Enterprise Data in a Relational Database is known as         
      persistence.


Architecture of an Enterprise App

Limitations of Traditional Approach
}Business logic is polluted with data accessing logic. Major role of Business tier is to concentrate on business logic alone but not on DB connectivity.
}Application portability to DB is lost.
Eg: SQL statements developed for one DBMS    may or may not work if the DBMS changes (tightly coupled/ vendor)
}Mismatches between object oriented Data Model and Relational Model cannot be addressed.

Alternative ways for Traditional Approach 

DAO Approach

}In DAO approach all possible data access operations are centralised in few Java classes.

ORM approach

}It is a technique of mapping object oriented data representation to that of the relational Model.

Hibernate 

}Hibernate is an object relational mapping service implementation.
}Hibernate is used to build persistent tier for Java based business applications.
}We can use Hibernate service through Hibernate API.

Hibernate Architecture



Configuration file & Mapping file:

Mapping file

}It is text file where Hibernate application develops specify the domain object class name and its attributes relational table and corresponding column names are also specified here.
}Mapping object oriented data representation to relational data.
}Standard name for this file is “ ClassName.hbm.xml”.

Example:

Employee.Java

public class Employee {
   private int id;
   private String firstName; 
   private String lastName;   
   private int salary;  

   public Employee() {}
   public Employee(String fname, String lname, int salary) {
      this.firstName = fname;
      this.lastName = lname;
      this.salary = salary;
   }
   public int getId() {
      return id;
   }
   public void setId( int id ) {
      this.id = id;
   }
   public String getFirstName() {
      return firstName;
   }
   public void setFirstName( String first_name ) {
      this.firstName = first_name;
   }
   public String getLastName() {
      return lastName;
   }
   public void setLastName( String last_name ) {
      this.lastName = last_name;
   }
   public int getSalary() {
      return salary;
   }
   public void setSalary( int salary ) {
      this.salary = salary;
   }
}

There would be one table corresponding to each object you are willing to 
provide persistence. Consider above objects need to be stored and retrieved 
into the following RDBMS table:

create table EMPLOYEE (
   id INT NOT NULL auto_increment,
   first_name VARCHAR(20) default NULL,
   last_name  VARCHAR(20) default NULL,
   salary     INT  default NULL,
   PRIMARY KEY (id)
);

Based on the two above entities we can define following mapping file which instructs 
Hibernate how to map the defined classes to the database tables.


<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-mapping PUBLIC 
 "-//Hibernate/Hibernate Mapping DTD//EN"
 "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd"> 

<hibernate-mapping>
   <class name="Employee" table="EMPLOYEE">
      <meta attribute="class-description">
         This class contains the employee detail. 
      </meta>
      <id name="id" type="int" column="id">
         <generator class="native"/>
      </id>
      <property name="firstName" column="first_name" type="string"/>
      <property name="lastName" column="last_name" type="string"/>
      <property name="salary" column="salary" type="int"/>
   </class>
</hibernate-mapping>

Configuration file:

}It’s a text file which contains all DB connection details (driver, DB, authentication & connection pooling details)
}Hibernate uses this file to establish connection to that particular database server and generates that particular product native SQL code
}Standard name for this file is “ hibernate.cfg.xml”

Example: hibernate.cfg.xml (for MySQL)

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE hibernate-configuration SYSTEM 
"http://www.hibernate.org/dtd/hibernate-configuration-3.0.dtd">

<hibernate-configuration>
   <session-factory>
   <property name="hibernate.dialect">
      org.hibernate.dialect.MySQLDialect
   </property>
   <property name="hibernate.connection.driver_class">
      com.mysql.jdbc.Driver
   </property>

   <!-- Assume test is the database name -->
   <property name="hibernate.connection.url">
      jdbc:mysql://localhost/test
   </property>
   <property name="hibernate.connection.username">
      root
   </property>
   <property name="hibernate.connection.password">
      root123
   </property>

   <!-- List of XML mapping files -->
   <mapping resource="Employee.hbm.xml"/>

</session-factory>
</hibernate-configuration>

Hibernate Properties:

Following is the list of important properties you would require to configure for a databases in a standalone situation:
S.N.Properties and Description
1hibernate.dialect
This property makes Hibernate generate the appropriate SQL for the chosen database.
2hibernate.connection.driver_class
The JDBC driver class.
3hibernate.connection.url
The JDBC URL to the database instance.
4hibernate.connection.username
The database username.
5hibernate.connection.password
The database password.
6hibernate.connection.pool_size
Limits the number of connections waiting in the Hibernate database connection pool.
7hibernate.connection.autocommit
Allows autocommit mode to be used for the JDBC connection.
If you are using a database along with an application server and JNDI then you would have to configure the following properties:
S.N.Properties and Description
1hibernate.connection.datasource
The JNDI name defined in the application server context you are using for the application.
2hibernate.jndi.class
The InitialContext class for JNDI.
3hibernate.jndi.<JNDIpropertyname>
Passes any JNDI property you like to the JNDI InitialContext.
4hibernate.jndi.url
Provides the URL for JNDI.
5hibernate.connection.username
The database username.
6hibernate.connection.password
The database password.

Configuration, SessionFactory & session object:

Configuration

}Object oriented representation of hibernate configuration file along with mapping file is known as Configuration object.

SessionFactory (like Connection Factory)

}It is a factory of session objects. It is similar to data source object. It is heavy weight object that has to be constructed/created only once for the application.
}sessionFactory object produce light weight session objects.

Example:

      Configuration c= new Configuration(); c.configure();     //now the file loading takes place.
 SessionFactory sf= c.buildSessionFactory();
 Session s= sf.openSession();

Session object (like connection):

Session object is the persistence manager for the Hibernate application.
Session object provides the following methods to perform CRUD operations.}get/load (for retrieving a record)}update() (for updating a record)}delete()  (for deleting a record)}save()  (for inserting a record)

Entity Relationships:
}In relational model, entities(tables) are associated with the PrimaryKeyForiegnKey relationship.
}In object oriented model, one persistent class is associated with other persistent class through object references made as data members.

We have 4 kinds of relationships

}one to one
}one to many
}many to one
}many to many 

Example:

}One-to-One (1:1) – one employee works for one department.
}One-to-Many (1:N) or Many-to-One (N:1) depending upon from which perspective we are looking at the relationship. One employee works in many projects.
}Many-to-Many (N:M) – Many books are written by many authors.


HQL (Hibernate Query Language):

}To perform complex persistent operations, Session object provided normal methods which are not sufficient. They can act upon only one persistent object (i.e one record only).
}HQL is used to deal with multiple persistent objects with different criteria in DBMS independent manner.
}HQL is similar to SQL query with one major difference.
}SQL query is expressed in terms of table’s and column’s.
}HQL query is expressed in terms of persistent classes and their attributes.


Example:


String hql = “FROM Employee”;
Query query = session.createQuery(hql);
List result = query.list();

Query query1= Session.createQuery(“UPDATE Account a set a.balance = a.balance + 1000”);

we can also specify place holder in place of values. These are known as parameters of the query.

Query query2 = Session.createQuery(“ SELECT a FROM Account a where a.account=?”);
Query1.setParameter(0,accno);
List <Account> accounts = query1.list();


  • Keywords like SELECT , FROM and WHERE etc. are not case sensitive but properties like table and column names are case sensitive in HQL.


FROM Clause:

You will use FROM clause if you want to load a complete persistent objects into memory. Following is the simple syntax of using FROM clause:

Eg: String hql = "FROM Employee";
      Query query = session.createQuery(hql);
      List results = query.list();

If you need to fully qualify a class name in HQL, just specify the package and class name as follows:

Eg: String hql = "FROM com.hibernatebook.criteria.Employee";
      Query query = session.createQuery(hql);
       List results = query.list();

AS Clause:

The AS clause can be used to assign aliases to the classes in your HQL queries, specially when you have long queries. For instance, our previous simple example would be the following:

Eg: String hql = "FROM Employee AS E";
     Query query = session.createQuery(hql);
     List results = query.list();

The AS keyword is optional and you can also specify the alias directly after the class name, as follows:

Eg: String hql = "FROM Employee E";
      Query query = session.createQuery(hql);
      List results = query.list();

SELECT Clause:

The SELECT clause provides more control over the result set than the from clause. If you want to obtain few properties of objects instead of the complete object, use the SELECT clause. Following is the simple syntax of using SELECT clause to get just first_name field of the Employee object:

Eg: String hql = "SELECT E.firstName FROM Employee E";
      Query query = session.createQuery(hql);
      List results = query.list();

It is notable here that Employee.firstName is a property of Employee object rather than a field of the EMPLOYEE table.

WHERE Clause:

If you want to narrow the specific objects that are returned from storage, you use the WHERE clause. Following is the simple syntax of using WHERE clause:

Eg: String hql = "FROM Employee E WHERE E.id = 10 and e.salay >=10001";
      Query query = session.createQuery(hql);
      List results = query.list();

ORDER BY Clause:

To sort your HQL query's results, you will need to use the ORDER BY clause. You can order the results by any property on the objects in the result set either ascending (ASC) or descending (DESC). Following is the simple syntax of using ORDER BY clause:

Eg: String hql = "FROM Employee E WHERE E.id > 10 ORDER BY E.salary DESC";
      Query query = session.createQuery(hql);
      List results = query.list();

If you wanted to sort by more than one property, you would just add the additional properties to the end of the order by clause, separated by commas as follows:

Eg: String hql = "FROM Employee E WHERE E.id > 10 " +
             "ORDER BY E.firstName DESC, E.salary DESC ";
      Query query = session.createQuery(hql);
      List results = query.list();

GROUP BY Clause:

This clause lets Hibernate pull information from the database and group it based on a value of an attribute and, typically, use the result to include an aggregate value. Following is the simple syntax of using GROUP BY clause:

Eg: String hql = "SELECT SUM(E.salary), E.firtName FROM Employee E " +
             "GROUP BY E.firstName";
     Query query = session.createQuery(hql);
     List results = query.list();

Using Named Paramters:

Hibernate supports named parameters in its HQL queries. This makes writing HQL queries that accept input from the user easy and you do not have to defend against SQL injection attacks. Following is the simple syntax of using named parameters:

Eg: String hql = "FROM Employee E WHERE E.id = :employee_id";
     Query query = session.createQuery(hql);
     query.setParameter("employee_id",10);
     List results = query.list();

UPDATE Clause:

Bulk updates are new to HQL with Hibernate 3, and deletes work differently in Hibernate 3 than they did in Hibernate 2. The Query interface now contains a method called executeUpdate() for executing HQL UPDATE or DELETE statements.
The UPDATE clause can be used to update one or more properties of an one or more objects. Following is the simple syntax of using UPDATE clause:

Eg: String hql = "UPDATE Employee set salary = :salary "  +
             "WHERE id = :employee_id";
      Query query = session.createQuery(hql);
      query.setParameter("salary", 1000);
      query.setParameter("employee_id", 10);
      int result = query.executeUpdate();
      System.out.println("Rows affected: " + result);

DELETE Clause:

The DELETE clause can be used to delete one or more objects. Following is the simple syntax of using DELETE clause:

Eg: String hql = "DELETE FROM Employee "  +
             "WHERE id = :employee_id";
      Query query = session.createQuery(hql);
      query.setParameter("employee_id", 10);
      int result = query.executeUpdate();
      System.out.println("Rows affected: " + result);

INSERT Clause:

HQL supports INSERT INTO clause only where records can be inserted from one object to another object. Following is the simple syntax of using INSERT INTO clause:

Eg: String hql = "INSERT INTO Employee(firstName, lastName, salary)"  +
             "SELECT firstName, lastName, salary FROM old_employee";
      Query query = session.createQuery(hql);
       int result = query.executeUpdate();
       System.out.println("Rows affected: " + result);


Named Query:

Employee.hbm.xml
}<query name = “salRange”>
FROM Employee e WHERE e.salary BETWEEN :lower AND :upper </query>

In Java class

}Query q = session.getNamedQuery(“salRange”);
}q.setParameter(“lower”, 10000);
}q.setParameter(“upper”, 50000);
}List<Employee> l = q.list();
 

Advantage:

}Without touching source code we can change the query
}Hibernate code will be less polluated with HQL.


Criteria API:
}This is another style of querying the DB. This is done without directly using either HQL or SQL and by only using a set of library methods queries are created dynamically and programmatically
Eg:
Criteria c= session.createCriteria (Employee.class);
Criterion cn = Restrictions.gt(“salary”, 9000f);
// salary>9000
c.add(cn); 
List< Employee> emps = c.list();
It is useful only for retrieval.


Example: 

1. Criteria cr = session.createCriteria(Employee.class); // To get records having salary more than 2000cr.add(Restrictions.gt("salary", 2000)); // To get records having salary less than 2000cr.add(Restrictions.lt("salary", 2000)); // To get records having fistName starting with zaracr.add(Restrictions.like("firstName", "zara%")); // Case sensitive form of the above restriction.cr.add(Restrictions.ilike("firstName", "zara%")); // To get records having salary in between 1000 and 2000cr.add(Restrictions.between("salary", 1000, 2000)); // To check if the given property is nullcr.add(Restrictions.isNull("salary")); // To check if the given property is not nullcr.add(Restrictions.isNotNull("salary")); // To check if the given property is emptycr.add(Restrictions.isEmpty("salary")); // To check if the given property is not emptycr.add(Restrictions.isNotEmpty("salary"));


2. Criteria cr = session.createCriteria(Employee.class);

Criterion salary = Restrictions.gt("salary", 2000);
Criterion name = Restrictions.ilike("firstNname","zara%");

// To get records matching with OR condistions
LogicalExpression orExp = Restrictions.or(salary, name);
cr.add( orExp );


// To get records matching with AND condistions
LogicalExpression andExp = Restrictions.and(salary, name);
cr.add( andExp );

List results = cr.list();
You can create AND or OR conditions using LogicalExpression restrictions as follows:


Persistent object has 4 life cycle states.


}Transient state ( new state)

Persistent object is not yet persisted into the database.

}Persisted / manages state.

Persistent object has identify in the database and is associate with persistent.

}Detached state.

Persistent object has identify in the database but it is not synchronized with database as it is deassociated with persistent context.

}Removed / dead state.

When object state is removed from DB, it loses identity and it is said to be dead.



Connection Pooling in Hibernate:


There are two kinds of application
}Standalone application
}Container Managed

Standalone application:

}In this case third party provide connection pooling software to be usedEg: Apache dbcp, c3po , etc.

In hibernate configuration file

} <property name =”dialect”>….</property>
}<property name =”c3po.min_size> 5</property>
}<property name= “c3po.max_size>50</property>
}<property name=”c3po.timeout>300</property>
}//sec can object ideal
}<property name=”c3po.max_statements”>50</property>
}// max prepared statement kept in cache
}<property name=”show_sql”> true</property>

Managed Environment: 

}If hibernate is used in a web application or in an EJB, we instruct hibernate to lookup for the connection pool (DataSource) and get the pooled connections.}<property name =”dialect”>….</property>}<property name=”show_sql”> true</property>
}Data source is different for Tomcat & Weblogic .

Multiple DB’s from Hibernate Application:

}Develop one Hibernate configuration file per DB}Create multiple SessionFactory objects
}Get the session object from that sessionFactory which represents a particular DB communication.
}SessionFactory sfOracle= new Configuration().configure().buildSessionFactory();
}SessionFactory sfSysbase= new Configuration().configure(“sysbase.cfg.xml”).buildSessionFactory();

Annotations: 

Annotations provide data about a program that is not part of the program itself.
So far you have seen how Hibernate uses XML mapping file for the transformation of data from POJO to database tables and vice versa.
Hibernate annotations is the newest way to define mappings without a use of XML file. You can use annotations in addition to or as a replacement of XML mapping metadata.

}@Entity Annotation: we used the @Entity annotation to the Employee class which marks this class as an entity bean.

}@Table Annotation:The @Table annotation allows you to specify the details of the table that will be used to persist the entity in the database. Its allow you to override the name of the table, its catalogue, and its schema.
}@Id Annotations:Each entity bean will have a primary key, which you annotate on the class with the @Id annotation.
}@Column Annotation:The @Column annotation is used to specify the details of the column to which a field or property will be mapped. You can use column annotation with the following most commonly used attributes name, length , nullable & unique.

Example:

import javax.persistence.*;

@Entity
@Table(name = "EMPLOYEE")
public class Employee {
   @Id @GeneratedValue
   @Column(name = "id")
   private int id;

   @Column(name = "first_name")
   private String firstName;

   @Column(name = "last_name")
   private String lastName;

   @Column(name = "salary")
   private int salary;  

   public Employee() {}
   public int getId() {
      return id;
   }
   public void setId( int id ) {
      this.id = id;
   }
   public String getFirstName() {
      return firstName;
   }
   public void setFirstName( String first_name ) {
      this.firstName = first_name;
   }
   public String getLastName() {
      return lastName;
   }
   public void setLastName( String last_name ) {
      this.lastName = last_name;
   }
   public int getSalary() {
      return salary;
   }
   public void setSalary( int salary ) {
      this.salary = salary;
   }
}

No comments:

Post a Comment

Java Packages Interview Question & Answers

All Packages Q) Thread Class Methods: - getName() run() getPriority() Sleep() isA...