Hibernate Querying

Topics in This Section


  •  Briefly review SQL querying
  •  Hibernate’s different approaches to querying a database

Querying for Data


  • Pull back specific data from a database based on specific requirements
  • Retrieve a specific object
  • Retrieve a collection of a specific object type
  • Retrieve a collection of different object types
  • In the database, handled through the Structured Query Language (SQL)
  • SELECT statements for querying

Querying Terminology

Restriction

Narrowing down the results (rows) based on specified criteria
In SQL, accomplished with the use of conditions appearing in ‘where’ clause
 Example
 SELECT * FROM EBILL WHERE EBILL_ID=1;

Projection

 Narrowing down the data (columns) we return
In SQL, accomplished by identifying columns in the ‘select’ clause
Example
SELECT EBILL_ID FROM EBILL WHERE AMOUNT > 1000;

Aggregation

Grouping similar results together based on common attributes
Example
SELECT EBILLER_ID, AVG(BALANCE) FROM EBILL GROUP BY EBILLER_ID;

SQL Query Options

SELECT <column(s)> // projection
FROM <table(s)>
[ WHERE ] // restriction
<condition(s)>
[ ORDER_BY ] // ordering
<ordering(s)>
[ GROUP BY ] // aggregation
<column(s)>
[ HAVING ] // group restriction
<condition(s)>

Querying with Hibernate

Provides multiple interfaces for querying
  • Query by ID
  • Query by Criteria
  • Query by Example
  • Hibernate Query Language
  • Native SQL calls through Hibernate

Query by ID

  • Retrieve an object by its ID Most common and easiest approach to obtaining objects
  • Fastest type of query, but can only return a single object at a time
  • Assuming primary key index on the id column
Account account = (Account)session.get(Account.class,accountId);

Query by Criteria

Hibernate provides alternate ways of manipulating objects and in turn data available in RDBMS tables. One of the methods is Criteria API which allows you to build up a criteria query object programmatically where you can apply filtration rules and logical conditions.

Restrictions with Criteria:  You can use add() method available for Criteria object to add restriction for a criteria query. Following is the example to add a restriction to return the records with salary is equal to 2000:

Criteria cr = session.createCriteria(Employee.class);
cr.add(Restrictions.eq("salary", 2000));
List results = cr.list();

You can create AND or OR conditions using LogicalExpression restrictions as follows:

Criteria cr = session.createCriteria(Employee.class);
Criterion salary = Restrictions.gt("salary", 2000);
Criterion name = Restrictions.ilike("firstNname","zara%");
LogicalExpression orExp = Restrictions.or(salary, name);
cr.add( orExp );
List results = cr.list();


Set Projection on specific properties.

criteria.setProjection( Projections.projectionList()
.add( Projections.property("ename") )
    .add( Projections.property("salary") )
  );

Query by Example 

Set up  example object(s) for Hibernate to use to generate a database query.
Create ‘Example’ criterion based on these objects
org.hibernate.criterion.Example
Create by using static create(Object obj);
Creates an Example object used for querying for the supplied object type

AccountOwner owner = new AccountOwner();
owner.setLastName("Hall");
Example exampleOwner = Example.create(owner)
List hallList = session createCriteria(AccountOwner.class)
.add(exampleOwner)
.list();

Hibernate Query Language

  • Hibernate created a new language named Hibernate Query Language (HQL), the syntax is quite similar to database SQL language. The main difference between is HQL uses class name instead of table name, and property names instead of column name.
  • Instead of returning plain data, HQL queries return the query result(s) in the form of object(s)/tuples of object(s) that are ready to be accessed, operated upon, and manipulated programmatically. This approach does away with the routine task of creating and populating objects from scratch with the "resultset" retrieved from database queried.
  • HQL fully supports polymorphic queries. That is, along with the object to be returned as a query result, all child objects (objects of subclasses) of the given object shall be returned.
  • HQL facilitates writing database-type independent queries that are converted to the native SQL dialect of the underlying database at runtime. This approach helps tap the extra features the native SQL query provides, without using a non-standard native SQL query.

 HQL Syntax


Clauses in the HQL are: 
from , select , where , order by ,group by

Aggregate functions are:
avg(...), sum(...), min(...), max(...) 
count(*)
count(...), count(distinct ...), count(all...)

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.
String hql = "FROM Employee E WHERE E.id = :employee_id";
Query query = session.createQuery(hql);
query.setParameter("employee_id",10);
List results = query.list();

Native SQL calls through Hibernate

You can use native SQL to express database queries if you want to utilize database-specific features such as query hints or the CONNECT keyword in Oracle. Hibernate 3.x allows you to specify handwritten SQL, including stored procedures, for all create, update, delete, and load operations.

Returning Scalar Values – All Columns

Query getEBills = session.createSQLQuery("SELECT * FROM EBILL"); 
     List listOfRowValues = getEBills.list();
     for (Object[] singleRowValues : listOfRowValues) {
  // returned in the order on the table
     long id = (long)singleRowValues[0];
     double balance = ( ) g [ ]; balance)singleRowValues[1];
      ...
     }

Return List of Objects

Query getEBills = session.createSQLQuery( "SELECT * FROM EBill")
.addEntity(EBill.class);
List ebills = getEBills.list();


HQL vs HCQL


HQL is to perform both select and non-select operations on the data,  but Criteria is only for selecting the data, we cannot perform non-select operations using criteria
HQL is suitable for executing Static Queries, where as Criteria is suitable for executing Dynamic Queries
Criteria used to take more time to execute then HQL
With Criteria we are safe with SQL Injection because of its dynamic query generation but in HQL as your queries are either fixed or parametrized, there is no safe from SQL Injection.

Thank You Prikshit





Hibernate and other ORM

PERSISTENCE


  • Ensure that state of object is accessible even after the application stops working.
  • Traditionally flat files were used to persist data.
  • File system has:
Lack of consistency.
Searching is difficult and time consuming.
Limited support to concurrent access.
So we move to databases(Relational database).

Problems with Jdbc 

Jdbc code is tightly coupled to the business logic in java class.
Code relies heavily on SQL.
Migrating from one database to another is difficult.
Relational databases doesn't address OOPS concepts.
Do not provide the required type support.

ORM


   Known as Object Relational Mapping.
Persists application objects to the tables in a relational database.
Hiding the underlying database architecture.
Converting data between relational databases and object oriented programming languages.

ORM FRAMEWORKS

Enterprise JavaBeans Entity Beans.
Castor.
Top Link.
Hibernate.
MyBatis formerly named iBatis.
Spring DAO ,etc.

HIBERNATE History


Started in 2001 by Gavin King.
Open source ORM tool.
Implementation of JPA.
Maps:
Java Class name   ----->  Table name.
Class fields           ----->  Table Columns.
Fields datatypes    ----->  Column Datatypes

WHY HIBERNATE

Makes object-relational mapping simple.
XML file defines the table that needs to be mapped to a particular class.
No need to modify application class to achieve OR mapping.
No need to worry about database changes.
Easy to navigate from db to db (Just change the dialect).
Supports many databases like
MySql, Oracle, Sybase, Derby

Classes And Interfaces

SessionFactory 
Interface that is available in org.hibernate package.
Helps in creation of Session instances.
Threads serving client request obtain sessions from factory.
Internal state is immutable.
One per database.

Session 
Interface present in org.hibernate package.
Key interface between Java application and Hibernate.
Lifecycle is bound by beginning and ending of transaction.
Short-Lived object.
Offer create, read, delete operations for instances.

Configuration
Class present in org.hibernate.cfg package.
Allows the application to specify mapping files.
Used to create session factory via buildSessionFactory().
Usually single instance gets created.


Transaction
Interface present in org.hibernate package.
Associated with a Session.
Usually initiated by a call to beginTransaction() method.
commit() method is used to end the transaction.

Query 
Interface present in org.hibernate package.
Instance gets created by calling Session.createQuery().
Lifespan is bound to the session lifespan.
Used to perform query (HQL).
Gets executed by calling list(), scroll() or iterate().


HQL

Hibernate Query Language.
Quite similar to SQL.
HQL uses class name instead of table name, and property names instead of column name.
Insert query doesn't have VALUES keyword.
Also supports insertion of values from other table like:

"insert into Object (id, name) select oo.id, oo.name from OtherObject oo";

IBATIS

Is SQL Centric Tool.
Currently InActive.
MyBatis is currently used.
Direct control over SQL queries.
Used when you need to write complicated sql queries.
Basically used when only fetching is required.
Maps result set with objects.

DIFFERENCES


Ibatis maps ResultSet to POJO Objects. Hibernate maps POJO Objects to database tables.
Use of Store Procedure is quite easy in Ibatis rather than Hibernate.                  
Ibatis use SQL(quite dependent on database) and Hibernate use HQL(quite independent of database).
In Ibatis user have to spend time on writing SQL.

Basic Code Examples




Introduction to Hibernate

Introduction to Hibernate Framework

  • Features and benefits of Hibernate Framework
  • Architecture of Hibernate Framework
  • Introduction to Persistence Lifecycle in Hibernate Framework

Introduction to Hibernate Framework


 Hibernate is object-relational mapping framework for java. It simplifies the development of java application to interact with the database. Hibernate is an open source, lightweight, ORM (Object Relational Mapping) tool. The ORM tool internally uses the JDBC API to interact with the database



How Hibernate Works

Firstly we need to load the configuration xml because once we load it , automatically mapping file will be loaded as it is registered in configuration file.
To load configuration file, we need to create the object of Configuration class and need to call configure() method.

Configuration cf = new Configuration();
cf.configure(“hibernate.cfg.xml”);

cf will read data from hibernate.cfg.xml, stores the data in different variables and all these variables are grouped into one high level hibernate object we call as SessionFactory object.

SessionFactory sf =  cf.buildSessionFactory();

SessionFactory is an interface and SessionFactoryImpl is implemented class for it, So internally we create object of SessionFactoryImpl class and stores it in interface reference.

So sf contains all data regarding configuration file. Then Session is created. It is also an interface and SessionImpl is implemented class. Whenever session is opened, internally database connection will get opened.

Session session = sf.openSession();
sf = SessfionFactory object

While working on insert,update,delete hibernate needs a logical transaction, but for select it doesn't require any transaction. In order to begin transaction, we need to call a method beginTransaction() given by Session Interface

Transaction tx = session.beginTransaction();

We use following Session methods to move objects from application to database

session .save(s)                 :   Inserting object ‘s’ into database
session.update(s)               : Updating object ‘s’ in the database
session.load(s)                 : Selecting objcet ‘s’ object
session.delete(s)                 : Deleting object ‘s’ from database
Finally we need to call commit() in transaction.
tx.commit();
And  we to need to close connection as 
session. close()
And finally close SessionFactory as
sf.close()

Features of Hibernate

Transparent Persistence
Here, Transparent mean complete seperation of concerns between the persistent classes and the persistent logic where the persistent classes are unaware of and have no dependency to the- persistence mechanism Hibernate doesnot require that any special superclasses or interfaces to be implemented by the persistent classes.

Object-Oriented Query Language
Hibernate uses HQL(Hibernate Query Language) and HQL is an object-oriented query language similar to SQL but instead of operating on tables and columns, HQL works with persistent objects and its properties. It is database independent query language because instead of table name, we use class name in HQL. It provides full support for polymorphic queries.

A query like:
from Cat as cat
returns instances not only of cat but also of its subclasses. Hibernate query can name any java class in where clause and the query will return instances of all persistent classes that extend that class.
Automatic Primary Key Generation
There are multiple key generation strategies. Increment keyword is used for automatic primary key generation.

Lazy Loading
It decides when to load the child object while loading the parent object. The default behaviour is to load 'property values eagerly' and to load 'collections lazily'

Also @OneToMany and @ManyToMany associations are defaulted  to LAZY loading and @OneToOne and @ManyToOne are defaulted to EAGER Laoding. It is by default using xml mappings but not when using annotations.
To Enable lazy load when we are using annotations we must use

"fetch="FetchType.LAZY"

FetchType.LAZY = Doesn’t load the relationships unless explicitly “asked for” via getter(not to load the child )

FetchType.EAGER = Loads ALL relationships

Object/Relational Mapping
It maps the persistent objects to the columns of the tables in the database. Mapping can be done using xml file as well as by using annotations.

Benefits of Hibernate

OpenSource and lightweight : Hibernate Framework is open source under LGPL license and lightweight

Database Independent Query: Hibernate has its own query language i.e HQL. It is object-oriented version of SQL. It generates the database independent queries. We don't need to write database specific queries. If we change our database, then also application will work.

Automatic Table Creation: Hibernate provide facility to create the tables of database automatically.

Fast Performance : The performance of hibernate framework is fast because cache is internally used in hibernate framework. There are two types of cache in hibernate framework- first level cache and second level cache. First level cache is enabled by default and you donot need to do anything to get this functionality working. Infact, you cannot disable it forcefully

First Level Cache 
It is associated with session object. Session Object is created on demand from session factory and it is lost, once session is closed. Similarly, first level cache associated with session object is available till session object is alive. It is available to that session object only not accessible to any other session objects. When we query entity for the first time, it is retrived from the database and stored in the first level cache associated with the session. 




If we query the same object again with the same session, It will be loaded from the cache and no sql query is executed. Loaded entity can be removed from the session using evict() method. Whole session cache can be removed using clear() method. It will remove all the entities stored in cache.

Second Level Cache
It is created in the session factory scope and is available to all sessions which are created using particluar session factory. It means if one session factory is closed, all the cache associated with it die.


When session try to load an entity, it firstly looks into the first level cache. If cached copy of the entity is present, it is returned as result of load method. If there is no cached entity, Second level cache is looked for cached entity. If Second level cache has cached entity, it is returned as a result of load method. But, before returning the entity, It is stored in first level cache also so that next innvocation for entity will return the entity from first level cache itself and there is no need to go to second level. If entity is not found n both the levels, then database query is executed and the entity is stored in both the cache levels before returning the response.

Architecture of Hibernate

The Hibernate architecture includes many objects: session factory, transaction factory, connection factory, session, transaction etc. There are 4 layers in hibernate architecture: -java application layer, hibernate framework layer, backhand api layer and database layer

High level architecture of Hibernate with mapping file and configuration file.



Elements of Hibernate Architecture

Session Factory: The org.hibernate.SessionFactory interface provides factory method to get the object of Session. It holds second level cache (optional) of data. The SessionFactory is a factory of session and client of ConnectionProvider. 

Session: The session object provides an interface between the application and data stored in the database. It is a short-lived object and wraps the JDBC connection.  It holds a first-level cache (mandatory) of data. The org.hibernate.Session interface provides methods to insert, update and delete the object.

Transaction: The org.hibernate.Transaction interface provides methods for transaction management.

Connection Provider: It is the factory of JDBC connections.

Transaction Factory: It is factory of transaction

Persistence Lifecycle

      Hibernate  is a transparent persistence mechanism - Classes are unaware of their own persistence capability. It has three states respect to its persistence lifecycle which are transient, persistent and detached. In a lifecycle, the object can transition from transient to persistent to detached states.


Transient Objects 
Objects instantiated using new operator aren't immediately persistent. Their state is transient. They aren't associated with any database table row. When that object is de-referenced it loses its state and goes to detached state which will be eligible to garbage collected. For an instance to transition from transient to persistent state requires a save() call to persistence manager 

Persistent Objects
A persistent instance is any instance with database entity. Persistent instance may be made transient via delete() call to persistence manager, resulting in deletion of corresponding row of the database. Persistent objects are synchronized with the database.

Detached Objects
Detached objects are no longer synchronized with the database. Persistent instances are detached when we close() the session. 
Evict() method of session can be used to detach the object from session cache. 

  How to Re-attach a detached Object?
 Both update() and merge() methods in hibernate are used to convert the object which is in detached state into persistence state.


Thank You Amarpreet