Hibernate


Hibernate
Hibernate is a backend framework, free to use, open source developed purely in java. Its working based on ORM – Object Relational Mapping.
Hibernate framework simplifies the development of java application to interact with the database. Hibernate is an open source, lightweight, ORM (Object Relational Mapping) tool.   An ORM tool simplifies the data creation, data manipulation and data access. It is a programming technique that maps the object to the data stored in the data

 Advantages of using Hibernate
In place of JDBC we can use hibernate. If we use JDBC to interact with the database, we need to develop several statements (steps) to send a SQL Query to the database like registering a driver, establishing a database connection object, getting a statement object, comparing SQL Query, sending SQL Query to the database, getting the results from the database, processing those results and finally closing all the JDBC related resources.
While using hibernate no need for any of these steps, straightaway pass java object to the hibernate framework. Hibernate framework will take care of interacting with JDBC API, like registering a driver, establishing a connection object, composing sql query based on data of java object etc.
Java program will be independent of database code, so we can change the database like oracle, MySql….. we just have to change one configuration file to make the changes.
JDBC gets the result immediately after getting the query, it doesn’t check if the user is using that result or not. In Hibernate it waits till the user to use that row, then sends the query and gets the result.
Hibernate Architecture There are 4 layers in hibernate architecture java application layer, hibernate framework layer, backhand api layer and database layer.Let's see the diagram of hibernate architecture
This is the high level architecture of Hibernate with mapping file and configuration file.
Hibernate framework uses many objects session factory, session, transaction etc. alongwith existing Java API such as JDBC (Java Database Connectivity), JTA (Java Transaction API) and JNDI (Java Naming Directory Interface).
high level architecture

Elements of Hibernate Architecture  For creating the first hibernate application, we must know the elements of Hibernate architecture. They are as follows:
SessionFactory The SessionFactory is a factory of session and client of ConnectionProvider. It holds second level cache (optional) of data. The org.hibernate.SessionFactory interface provides factory method to get the object of Session.
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 is factory of Transaction, Query and Criteria. It holds a first-level cache (mandatory) of data. The org.hibernate.Session interface provides methods to insert, update and delete the object. It also provides factory methods for Transaction, Query and Criteria.
Transaction  The transaction object specifies the atomic unit of work. It is optional. The org.hibernate.Transaction interface provides methods for transaction management.
ConnectionProvider  It is a factory of JDBC connections. It abstracts the application from DriverManager or DataSource. It is optional.TransactionFactory  It is a factory of Transaction. It is optional.
Two types of loading data from database in hibernate
Eager Loading
Framework loads data immediately after executing query to get the data,.
Lazy Loading
It does not load data immediately when asked to load, it will be looking for the statement which is using that data, just before executing that statement framework will be loading that data.
Hibernate supports both type of loading and the default one is lazy loading.
Difference between JDBC and Hibernate
In case of JDBC no cache mechanism, no temporary memory to store data. Every time connects to the db and gets the data (a network flow from java program to database).
Hibernate supports two levels of cache mechanism: First Level cache and Second Level.
First level cache is the default. Second level we have to provide explicitly.

JDBC is not providing any auto increment values to the unique column of the table. (In general for every table there should be a auto increment column.) JDBC programmer has to manually increment the unique column(used to identify the row and count total number of rows).
Hibernate supports auto generated random unique number.

JDBC supports only updatable operations without transactions. No transaction boundaries required while updating, editing or deleting a row. No updatable operations without a transaction in case of Hibernate.
E.g.: In a table if column of a particular row are changed at different statement, Framework updates only at the time of commit statement. It will update all changes at once. JDBC modifies immediately, even if updating same row and same column again and again. Hibernate supports Polymorphic mappings and Association mappings, through this we can easily achieve relationships among the tables.
Mainly three types of relations among the tables
One-to-one: One row of one table mapping with a particular row of another table.
One-to-many: One row of 1st table mapping with multiple rows of 2nd table.
Many-to-many: One row of 1st table mapping with Multiple rows of 2nd table. One row of 2nd table mapping with multiple rows of 1st table.
Hibernate supports Annotation mappings
EJB3 and Hibernate developers provide several annotations used for providing a mapping (easy way of providing a mapping). No need for additional classes for mapping. Annotation itself contains them, it gives ultimate performance.

How to use Hibernate Framework

EclipseàNewàProject àJava Project. Project Name: app1
Updating the Build Path:
Right click on app1àPropertiesàJava Build PathàLibrariesàAdd External JARsàBrowse to
Location of the Hibernate un zipped  folder And  add all jar files inside HIBERNATE\hibernate-distribution-4..1.1\lib\required by selecting all.
Again Add the Oracle jdbc driver jar file
D:\oracle\app\oracle\product\10.2.0\server\jdbc\lib\ojdbc14.jar
Copy the hibernate.cfg.xml and log4j.properties file from inside Hibernate unzipped bundle go to D:\Java\hibernate\project\tutorials\web\src\main\resources\
Right click on src and paste. The hibernate.cfg.xml is used to identify the type of database, driver class name, url etc.
The log4j.properties file is not mandatory but is advisable.
While developing for the first time since we won’t be knowing the tags of the hibernate.cfg.xml file, we are using the model file.
Inside hibernate.cfg.xml file make the following changes marked in bold:
<hibernate-configuration>

<session-factory>

<!-- Database connection settings -->
<propertyname="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<propertyname="connection.url">jdbc:oracle:thin:@localhost:1521:XE</property>
<propertyname="connection.username">system</property>
<propertyname="connection.password">password</property>

<!-- JDBC connection pool (use the built-in) -->
<propertyname="connection.pool_size">2</property>

<!-- SQL dialect -->
<propertyname="dialect">org.hibernate.dialect.OracleDialect</property>


<!-- Enable Hibernate's current session context -->
<propertyname="current_session_context_class">org.hibernate.context.ManagedSessionContext</property>

<!-- Disable the second-level cache  -->
<propertyname="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>

<!-- Echo all executed SQL to stdout -->
<propertyname="show_sql">true</property>

<!-- Drop and re-create the database schema on startup -->
<propertyname="hbm2ddl.auto">create</property>

<mappingresource="com/lara/Person.hbm.xml"/>
</session-factory>

</hibernate-configuration>
The SQL dialect specifies the type of database we are using to the Framework.

Right Click on srcàNewàClass
Person.java (This type of class is called as POJO (Plain Old Java object) class
package com.lara;

public class Person {
private String id;
private String firstname;
private String lastname;
private int age;
public String getId() {
returnid;
}
public void  setId(String id) {
this.id = id;
}
public String getFirstname() {
returnfirstname;
}
public void  setFirstname(String firstname) {
this.firstname = firstname;
}
public String getLastname() {
returnlastname;
}
public void  setLastname(String lastname) {
this.lastname = lastname;
}
publicint getAge() {
returnage;
}
public void  setAge(int age) {
this.age = age;
}                
}
This type of class called useBean in JSP,  formBean in Struts and POJO in hibernate.
hibernate\project\tutorials\web\src\main\resources\org\hibernate\tutorial\domain\Person.hbm.xml and paste it by right clicking on lara folder in eclipse).

Make the following changes in Person.hbm.xml
<hibernate-mappingpackage="com.lara">

<classname="Person"table="PERSON">
<idname="id"column="PERSON_ID">
<generatorclass="native"/>
</id>
<propertyname="age"/>
<propertyname="firstname"/>
<propertyname="lastname"column="last_name"/>

</class>
</hibernate-mapping>

Manager.java
package com.lara;

import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;

public class Manager {
public static void main(String[] args) {
Person p1 = new Person();
p1.setFirstname("abc");
p1.setLastname("xyz");
p1.setAge(25);

Configuration c1 = new Configuration();
c1.configure();

SessionFactory sf = c1.buildSessionFactory();
Session session = sf.openSession();
}
}
SQL query sent to db
CREATE TABLE  "PERSON"
(        "PERSON_ID" VARCHAR2(255) NOT NULL ENABLE,
"AGE" NUMBER(10,0),
"FIRSTNAME" VARCHAR2(255),
"LAST_NAME" VARCHAR2(255),
PRIMARY KEY ("PERSON_ID") ENABLE
)
/

Manager classs  :
package com.lara;
import java.util.Scanner;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.service.ServiceRegistry;
import org.hibernate.service.ServiceRegistryBuilder;
public class Manager1
{
public static void main(String[] args)
{
Configuration con = new Configuration();
con.configure();
ServiceRegistry sr = new ServiceRegistryBuilder().
applySettings(con.getProperties()).build();
SessionFactory sf = con.buildSessionFactory(sr);
Session s1 = sf.openSession();
/*   Person p1 = new Person();
p1.setFirstName("lara");
p1.setLastName("rst");
p1.setAge(22);
Person p2 = new Person();
p2.setFirstName("vijay");
p2.setLastName("kumar");
p2.setAge(26);
s1.beginTransaction();
s1.save(p1);
s1.save(p2);
s1.getTransaction().commit();
s1.flush();
s1.close();  */
By using Sccanner class :
/*   Scanner sc = new Scanner(System.in);
String firstName, lastName, decider;
int age;
Person p1 = null;
s1.beginTransaction();
do
{
p1= new Person();
System.out.println("Enter first name : ");
p1.setFirstName(sc.next());
System.out.println("Enter last name : ");
p1.setLastName(sc.next());
System.out.println("Enter age : ");
p1.setAge(sc.nextInt());
s1.save(p1);
System.out.println("Do you want to save one more y/n : ");
decider = sc.next();
}while("y".equals(decider));
s1.getTransaction().commit();   */

/*   Person p1 = (Person)s1.load(Person.class, 1);
//Person p1 = (Person)s1.get(Person.class, 2);
System.out.println(p1.getId()+ " - " +p1.getFirstName()+ " - "
+p1.getLastName()+ " - "+p1.getAge());*/
/*   Person p2 = (Person)s1.load(Person.class, 2);
p2.setFirstName("hello");
p2.setLastName("test");
s1.beginTransaction();
s1.update(p2);
s1.getTransaction().commit(); */

/*   Person p3 = (Person)s1.load(Person.class, 1);
s1.beginTransaction();
s1.delete(p3);
s1.getTransaction().commit(); 
System.out.println(" done ");*/
}

}
Transaction Interface in Hibernate     In hibernate framework, we have Transaction interface that defines the unit of work. It maintains abstraction from the transaction implementation (JTA,JDBC).
A transaction is associated with Session and instantiated by calling session.beginTransaction().
The methods of Transaction interface are as follows:
void begin() starts a new transaction.
void commit() ends the unit of work unless we are in FlushMode.NEVER.
void rollback() forces this transaction to rollback.
void setTimeout(int seconds) it sets a transaction timeout for any transaction started by a subsequent call to begin on this instance.
boolean isAlive() checks if the transaction is still alive.
void registerSynchronization(Synchronization s) registers a user synchronization callback for this transaction.
boolean wasCommited() checks if the transaction is commited successfully.
HCQL (Hibernate Criteria Query Language)
The Hibernate Criteria Query Language (HCQL) is used to fetch the records based on the specific criteria. 
Criteria Interface
The Criteria interface provides many methods to specify criteria. The object of Criteria can be obtained by calling the createCriteria() method of Session interface.
Syntax of createCriteria() method of Session interface
public Criteria createCriteria(Class c)  
The commonly used methods of Criteria interface are as follows:
public Criteria add(Criterion c) is used to add restrictions.
public Criteria addOrder(Order o) specifies ordering.
public Criteria setFirstResult(int firstResult) specifies the first number of record to be retreived.
public Criteria setMaxResult(int totalResult) specifies the total number of records to be retreived.
public List list() returns list containing object.
public Criteria setProjection(Projection projection) specifies the projection.

Example :
Criteria ctr = s1.createCriteria(Person.class);
ctr.add(Restrictions.eq("firstName", "lara"));
ctr.add(Restrictions.gt("age", 15));
ctr.add(Restrictions.like("lastName", "%s%"));
List<Person> list = ctr.list()
Example2 :
Criteria ctr = s1.createCriteria(Person.class);
Criterion c1 = Restrictions.eq("firstName", "lara");
//ctr.add(c1);
Criterion c2 = Restrictions.gt("age", 25);
Criterion c3 = Restrictions.or(c1, c2);
ctr.add(c3);
List<Person> list = ctr.list();
Example 3
List<Person> list = s1.createCriteria(Person.class).add(Restrictions.gt("age", 25)).list();    
for (Person p1 : list)
{
System.out.println(p1.getId()+ " - " +p1.getFirstName()+ " - "
+p1.getLastName()+ " - " +p1.getAge());
System.out.println("------------");
}    

createSQLQuery():
List<Object[]> list2 = s1.getNamedQuery("q1").list();
//List<Object[]> list2 = s1.getNamedQuery("q2").list();                      
//List<Object[]> list2 = s1.getNamedQuery("q3").setInteger("param1", 22).list();                                  List<Object[]> list2 =
s1.getNamedQuery("q4").setInteger("param1",21).setString("param2", "hello").list();         
for (Object[] row : list2)
{
System.out.println(Arrays.toString(row));
System.out.println("-------");
}
HQL queary :  Hibernate Query Language (HQL) is same as SQL (Structured Query Language) but it doesn't depends on the table of the database. Instead of table name, we use class name in HQL. So it is database independent query language.
Advantage of HQL
There are many advantages of HQL. They are as follows:
database independent
supports polymorphic queries
easy to learn for Java Programmer
Query Interface    It is an object oriented representation of Hibernate Query. The object of Query can be obtained by calling the createQuery() method Session interface. The query interface provides many methods. There is given commonly used methods:
public int executeUpdate() is used to execute the update or delete query.
public List list() returns the result of the ralation as a list.
public Query setFirstResult(int rowno) specifies the row number from where record will be retrieved.
public Query setMaxResult(int rowno) specifies the no. of records to be retrieved from the relation (table).
public Query setParameter(int position, Object value) it sets the value to the JDBC style query parameter.
public Query setParameter(String name, Object value) it sets the value to a named query parameter.
Examples  :
Query query = s1.createQuery("from Person");    
Exp-1
Query query = s1.createQuery("from com.lara.Person where firstName = 'lara'");
Exp-2
Query query = s1.createQuery("from com.lara.Person where age < 25 or
firstName = 'lara'");
List<Person> list3 = query.list();
for (Person p1 : list3)
{
System.out.println(p1.getId()+ " - " +p1.getFirstName()+ " - "
+p1.getLastName()+ " - " +p1.getAge());
System.out.println("----------");
}

Exp-3
Query query = s1.createQuery("select firstName from com.lara.Person");
List<String> list3 = query.list();
for (String p1 : list3)
{
System.out.println(p1);
System.out.println("--------");
}
Exp-4
Query query = s1.createQuery("select firstName, lastName from com.lara.Person");
List<Object []> list3 = query.list();
for (Object[] p1 : list3)
{
System.out.println(Arrays.toString(p1));
System.out.println("--------");
}
Hibernate Named Query  The hibernate named query is way to use any query by some meaningful name. It is like using alias names. The Hibernate framework provides the concept of named queries so that application programmer need not to scatter queries to all the java code.
There are two ways to define the named query in hibernate:
by annotation
by mapping file.
BY using annotations : @NameQueries annotation is used to define the multiple named queries.   @NameQuery annotation is used to define the single named query.
Inside manager class
getNamedQuery()- Using Annotation

//List<Object[]> list2 = s1.getNamedQuery("q1").list();
//List<Person> list2 = s1.getNamedQuery("q2").list();                
//List<Person> list2 = s1.getNamedQuery("q3").setInteger("param1", 22).list();
List<Person>list2 = s1.getNamedQuery("q4").setInteger("param1",20).setString("param2","rst").list();
for (Person p1 : list2)
{
System.out.println(p1.getId()+ " - " +p1.getFirstName()+ " - "
+p1.getLastName()+ " - "+p1.getAge());
System.out.println("-------");
}    

New Java Project: app2
Update Java Build Path with jdbc driver, hibernate.jar and jar files in required folder.                         hibernate.cfg.xml
<hibernate-configuration>

<session-factory>

<!-- Database connection settings -->
<propertyname="connection.driver_class">oracle.jdbc.driver.OracleDriver</property>
<propertyname="connection.url">jdbc:oracle:thin:@localhost:1521:XE</property>
<propertyname="connection.username">system</property>
<propertyname="connection.password">password</property>

<!-- JDBC connection pool (use the built-in) -->
<propertyname="connection.pool_size">2</property>

<!-- SQL dialect -->
<propertyname="dialect">org.hibernate.dialect.OracleDialect</property>

<!-- Enable Hibernate's current session context -->
<propertyname="current_session_context_class">org.hibernate.context.ManagedSessionContext</property>

<!-- Disable the second-level cache  -->
<propertyname="cache.provider_class">org.hibernate.cache.NoCacheProvider</property>

<!-- Echo all executed SQL to stdout -->
<propertyname="show_sql">true</property>

<!-- Drop and re-create the database schema on startup -->
<propertyname="hbm2ddl.auto">create</property>

<mappingresource="com/lara/entity/Person.hbm.xml"/>

</session-factory>

</hibernate-configuration>

New class HibernatUtil in app2/src/com/lara/util/
package com.lara.util;

import org.hibernate.SessionFactory;
import org.hibernate.cfg.Configuration;
import org.hibernate.classic.Session;

public class HibernateUtil {
private static Session session = null;
//java program interacts with the Framework libraries through session obj.
static{ //initialize session object
Configuration config = new Configuration();
config.configure(); //looks for hibernate.cfg.xml inside classpath.
//src folder will be in classpath of eclipse.

SessionFactory sf = config.buildSessionFactory();
session = sf.openSession();
}
public static Session getSession()
{
returnsession;
}
public static void closeSession()
{
session.flush();
session.close();
}
}

Person.java in com/lara/entity (POJO class)
package com.lara.entity;

public class Person {
privateintpersonId;
private String firstName, lastName;
privateintage;
private String email;
publicint getPersonId() {
returnpersonId;
}
public void  setPersonId(int personId) {
this.personId = personId;
}
public String getFirstName() {
returnfirstName;
}
public void  setFirstName(String firstName) {
this.firstName = firstName;
}
public String getLastName() {
returnlastName;
}
public void  setLastName(String lastName) {
this.lastName = lastName;
}
publicint getAge() {
returnage;
}
public void  setAge(int age) {
this.age = age;
}
public String getEmail() {
returnemail;
}
public void  setEmail(String email) {
this.email = email;
}
}

For every POJO class we need one .hbm.xml file. It provides mapping between class_name and table name attribute. We can keep the hbm file in any location inside src folder with any name.
Create the Person.hbm.xml file inside entity folder (copy & paste).
app2/src/com/lara/entity/Person.hbm.xml
<hibernate-mappingpackage="com.lara.entity">

<classname="Person"table="PERSON">
<idname="personId"column="PERSON_ID">
<generatorclass="native"/>
</id>
<propertyname="age"/>
<propertyname="firstName"column="first_name"/>
<propertyname="lastName"column="last_name"/>
<propertyname="email"/>
</class>

</hibernate-mapping>

If column name is not provided we get the column name as the attribute name. so for age and email we get the column name as age and email only.
The <id> tag is used to provide primary key value. The personId is qualifying as a primary key column.

app2/src/com/lara/client/Manager1 (To demonstrate create and update operation)
package com.lara.client;

import org.hibernate.Session;

import com.lara.entity.Person;
import com.lara.util.HibernateUtil;

public class Manager1 {
public static void main(String[] args) {
Person p1 = new Person();
p1.setFirstName("Shiva");
p1.setLastName("Great Indian");
p1.setAge(23);
p1.setEmail("Shiva@lara.co.in");
//hibernate FW automatically provides auto incremented id.

Session session = HibernateUtil.getSession();
session.beginTransaction();
session.save(p1); //save Person obj. inside session obj.
session.getTransaction().commit();
HibernateUtil.closeSession();
}
}
Hibernate checks for Person table, if present drops it and creates new table.
Output console:
Hibernate: select hibernate_sequence.nextval from dual
Hibernate: insert into PERSON (age, first_name, last_name, email, PERSON_ID) values (?, ?, ?, ?, ?)
Query
CREATE TABLE  "PERSON"
(        "PERSON_ID" NUMBER(10,0) NOT NULL ENABLE,
"AGE" NUMBER(10,0),
"FIRST_NAME" VARCHAR2(255),
"LAST_NAME" VARCHAR2(255),
"EMAIL" VARCHAR2(255),
PRIMARY KEY ("PERSON_ID") ENABLE
)
/

To insert data into same table in multiple execution (update operation).
Change the <propertyname="hbm2ddl.auto">create</property>create to update.
As shown:<propertyname="hbm2ddl.auto">update</property>
The create type Drop’s and re-creates the database table.
The update type inserts a new row to the table on each execution. Generating a new unique Persion_ID for each row.

To demonstrate load operation
app2/src/com/lara/client/Manager2.java
package com.lara.client;

import org.hibernate.Session;

import com.lara.entity.Person;
import com.lara.util.HibernateUtil;

public class Manager2 {
public static void main(String[] args) {
Session session = HibernateUtil.getSession();
Person p1 = (Person) session.load(com.lara.entity.Person.class, 2);
//load one row having unique id as 2 into java program

System.out.println(10);
System.out.println(p1.getPersonId());
System.out.println(20);
System.out.println(p1.getFirstName());
System.out.println(30);
System.out.println(p1.getLastName());
System.out.println(p1.getAge());
System.out.println(p1.getEmail());                       
}
}
Output:
10
2
20
Hibernate: select person0_.PERSON_ID as PERSON1_0_0_, person0_.age as age0_0_, person0_.first_name as first3_0_0_, person0_.last_name as last4_0_0_, person0_.email as email0_0_ from PERSON person0_ where person0_.PERSON_ID=?
Shiva
30
Great Indian
23
Shiva@lara.co.in
While calling load or getPerson SELECT Query is not triggered. Before calling getFirstName select query is triggered. Till then firstName, lastName, age, email not available in Person object. After query is executed gets the values from database and stores them in Person object.
Initially Person object defined only with Person_Id.
This concept is called as Lazy loading.
To force the triggering of SELECT query on execution of load or getter methods, make the following changes inside the Person.hbm.xml file:
<classname="Person"table="PERSON"lazy="false">
Output:
Hibernate: select person0_.PERSON_ID as PERSON1_0_0_, person0_.age as age0_0_, person0_.first_name as first3_0_0_, person0_.last_name as last4_0_0_, person0_.email as email0_0_ from PERSON person0_ where person0_.PERSON_ID=?
10
2
20
Shiva
30
Great Indian
23
Shiva@lara.co.in
Query executed on calling load()method inside session object itself.
If we pass an Id that does not exist, we get ObjectNotFoundException.
Exception in thread "main" org.hibernate.ObjectNotFoundException: No row with the given identifier exists: [com.lara.entity.Person#5]
We can also use get method instead of the load method, while getting the values to p1 Person object
Person p1 = (Person) session.get(com.lara.entity.Person.class, 1);
The output will be same as while using load.
But if we use get to a row that does not exist, i.e., if we pass an Id that does not exist using get method, we get NullPointerException.
Exception in thread "main" java.lang.NullPointerException

Difference between load and get is:
If row is not available, load gives ObjectNotFoundException and get gives NullPointerException.
The get method just returns null, does not generate any Exception object.
The load method will be raising an exception, which creates and exception object and which in turn returns ONFE.
Best practice is to use get method and if p1 reference variable not pointing to any object, i.e., if p1 is null, don’t call get method.

Person p1 = (Person) session.get(com.lara.entity.Person.class, 10);
Here p1 will get a null because 10th row (row with Person_Id as 10) does not exist.
package com.lara.client;

public class Manager2 {
public static void main(String[] args) {
Session session = HibernateUtil.getSession();
Person p1 = (Person) session.get(com.lara.entity.Person.class, 10);
if(p1 != null)
{
System.out.println(10);
System.out.println(p1.getPersonId());
System.out.println(20);
System.out.println(p1.getFirstName());
System.out.println(30);
System.out.println(p1.getLastName());
System.out.println(p1.getAge());
System.out.println(p1.getEmail());                                   
}                
else
{
System.out.println("No row available with id as 10");
}
}
}
Output:
Hibernate: select person0_.PERSON_ID as PERSON1_0_0_, person0_.age as age0_0_, person0_.first_name as first3_0_0_, person0_.last_name as last4_0_0_, person0_.email as email0_0_ from PERSON person0_ where person0_.PERSON_ID=?
No row available with id as 10
Manager3.java in app2/com/lara/client
package com.lara.client;

import org.hibernate.Session;

import com.lara.entity.Person;
import com.lara.util.HibernateUtil;

public class Manager3 {
public static void main(String[] args) {
Session session = HibernateUtil.getSession();
Person p1 = (Person) session.load(com.lara.entity.Person.class, 3);
session.beginTransaction();
p1.setLastName("new lastname"); //modifies column
session.saveOrUpdate(p1);
p1.setAge(90);
session.saveOrUpdate(p1);
p1.setFirstName("new Kiran");
session.saveOrUpdate(p1);
session.getTransaction().commit();
HibernateUtil.closeSession();
}
}
getTransaction method is required for all updatable operations like update or delete.
Update triggered only once even though we called 3 times. Its triggered while committing Transaction.
Initially changes are stored in the Person object p1, which is in session object. When commit is executed, its moved from session object to database.
Manager4.java in app2/src/com/lara/client
package com.lara.client;

import org.hibernate.Session;

import com.lara.entity.Person;
import com.lara.util.HibernateUtil;

public class Manager4 {
public static void main(String[] args) {
Session session = HibernateUtil.getSession();
Person p1 = (Person) session.load(com.lara.entity.Person.class, 3);
Person p2 = (Person) session.load(com.lara.entity.Person.class, 3);
Person p3 = (Person) session.load(com.lara.entity.Person.class, 3);
Person p4 = (Person) session.load(com.lara.entity.Person.class, 3);
Person p5 = (Person) session.load(com.lara.entity.Person.class, 3);
HibernateUtil.closeSession();
}      }
Output:  Hibernate: select person0_.PERSON_ID as PERSON1_0_0_, person0_.age as age0_0_, person0_.first_name as first3_0_0_, person0_.last_name as last4_0_0_, person0_.email as email0_0_ from PERSON person0_ where person0_.PERSON_ID=?
SELECT query is triggered only once. After triggering for the 1st time, gets the data and stores in Person object inside session object. So from 2nd time onwards loads the values from the session object and won’t send the query.
This is called as First Level cache Management.
Manager5.java in app2/src/com/lara/client
package com.lara.client;

import org.hibernate.Transaction;
import org.hibernate.Session;

import com.lara.entity.Person;
import com.lara.util.HibernateUtil;

public class Manager5 {
public static void main(String[] args) {
Session session = HibernateUtil.getSession();
Person p1 = (Person) session.load(com.lara.entity.Person.class, 2);
Transaction tx = session.beginTransaction();
session.delete(p1);
session.delete(p1);
session.delete(p1);
tx.commit();
}
}
Delete query triggered only once, that too after commit.

Session object methods:
save, update, saveOrUpdate, delete.
Hibernate is using methods of session object. Except read, all methods should be inside Transaction object.
If transaction object not used, use session.getTransaction().commit();  instead of the tx.commit();

Book.java inside app2/com/lara/entity/ (POJO class)
package com.lara.entity;

public class Book {
privateintbookId;
private String title, author;
publicint getBookId() {
returnbookId;
}
public void  setBookId(int bookId) {
this.bookId = bookId;
}
public String getTitle() {
returntitle;
}
public void  setTitle(String title) {
this.title = title;
}
public String getAuthor() {
returnauthor;
}
public void  setAuthor(String author) {
this.author = author;
}
}
In the Person.hbm.xml file:
<hibernate-mappingpackage="com.lara.entity">

<classname="Book"table="BOOK"lazy="false">
<idname="bookId"column="BOOK_ID">
<generatorclass="native"/>
</id>
<propertyname="age"/>
<propertyname="title"/>
<propertyname="author"/>
</class>

</hibernate-mapping>
Update in cfg.xml file, if not updated.
Manager6 in app2/src/com/lara/client

package com.lara.client;

import org.hibernate.Session;
import org.hibernate.Transaction;

import com.lara.entity.Book;
import com.lara.util.HibernateUtil;

public class Manager6 {
public static void main(String[] args) {
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
Book b1 = new Book();
b1.setTitle("Java Made Easy");
b1.setAuthor("Shiva");
session.save(b1);
session.save(b1);
session.save(b1);
session.save(b1);
tx.commit();
}
}
Make sure there isn’t a BOOK table in db before executing Manager6.
Output: INSERT query only at the time of commit that too only once.
If <generatorclass="native"/>in .hbm.xml file is native, then only one sequence will be used for all the Tables which are interacting through hibernate.
The sequence is hibernate_sequence. For example if the unique Id for a row in one table is 22, and if we add another row in another table, then its unique id will be 23 and so on. It uses common auto increment sequence for all tables.
If row count common across all table go for generator class=”native”.
We can use a separate hbm file Book class
Create com/lara/entity/Book.hbm.xml file and save.
<hibernate-mappingpackage="com.lara.entity">

<classname="Book"table="BOOK"lazy="false">
Update in cfg.xml
<mappingresource="com/lara/entity/Person.hbm.xml"/>
<mappingresource="com/lara/entity/BOOK.hbm.xml"/>
We can have any number of mapping resource in cfg.xml file.
Always use separate mapping files for each Pojo class.

Manager6
package com.lara.client;

import org.hibernate.Session;

import org.hibernate.Transaction;

import com.lara.entity.Book;
import com.lara.util.HibernateUtil;

public class Manager6 {
public static void main(String[] args) {
Session session = HibernateUtil.getSession();
Transaction tx = session.beginTransaction();
Book b1 = new Book();
b1.setTitle("Hibernate Made Easy");
b1.setAuthor("Shiva");
session.save(b1);
tx.commit();
}
}
SELECT Max(Book_ID): reads Max. value of present BOOk_ID  and increments that and assigns as Unique ID.
All generator classes not supported by all databases.For example “identity” generator class not supported by oracle.
<generatorclass="identity"/>
Sequence:
<generator class="sequence"/>
Same as native.

hilo
<generatorclass="hilo"/>
Randomly generates one unique Id, using its own algorithm.
seqhilo
<generatorclass="seqhilo"/>
Applies the hilo algorithm to the sequence value of hibernate_native.

uuid
<generatorclass="uuid"/>
Unique id as a string. Change bookId to String type. Also change hbm2dll to create in hibernate.cfg.xml.<propertyname="hbm2ddl.auto">create</property>
Generates one String content for Book_Id.
Guid
<generator class="guid"/>
Here also a String is generated of id.

assigned
<generatorclass="assigned"/>
The framework (generator class) won’t provide any ID. We have to set explicitly through setter methods. For example: b1.setBookId(“b101”);

No comments:

Post a Comment