Thursday, October 27, 2011

Hibernate

About Hibernate in a line : Hibernate applications define persistent classes that are "mapped" to database tables. 

Saving data to a storage is called persistence.

Hibernate is an object-relational mapping (ORM) library for the Java language, providing a framework for mapping an object-oriented domain model to a traditional relational database. Hibernate solves object-relational impedance mismatch problems by replacing direct persistence-related database accesses with high-level object handling functions

Hibernate's primary feature is mapping from Java classes to database tables (and from Java data types to SQL data types). Hibernate also provides data query and retrieval facilities. 

Hibernate generates the SQL calls and attempts to relieve the developer from manual result set handling and object conversion and keep the application portable to all supported SQL databases with little performance overhead.

Mapping :
Mapping Java classes to database tables is accomplished through the configuration of an XML file or by using Java Annotations. When using an XML file, Hibernate can generate skeletal source codefor the persistence classes. This is unnecessary when annotations are used.

Facilities to arrange one-to-many and many-to-many relationships between classes are provided. In addition to managing associations between objects, Hibernate can also manage reflexiveassociations where an object has a one-to-many relationship with other instances of its own type

Persistence :
Hibernate provides transparent persistence for Plain Old Java Objects (POJOs). The only strict requirement for a persistent class is a no-argument constructor, not necessarily public. Proper behavior in some applications also requires special attention to the equals() and hashCode() methods

Collections of data objects are typically stored in Java collection objects such as Set and List. Java generics, introduced in Java 5, are supported. Hibernate can be configured to lazy load associated collections. Lazy loading is the default as of Hibernate 3

HQL (Hibernate Query Language) :
Hibernate provides an SQL inspired language called Hibernate Query Language (HQL) which allows SQL-like queries to be written against Hibernate's data objects

Integration :
Hibernate can be used both in standalone Java applications and in Java EE applications using servlets or EJB session beans. It can also be included as a feature in other programming languages. For example, Adobe integrated Hibernate into version 9 of ColdFusion (which runs on J2EE app servers)

Hibernate Annotation and many to One mapping, one to many etc..cascade is the key :) http://www.vaannila.com/hibernate/hibernate-tutorial/hibernate-tutorial.html
http://www.mkyong.com/tutorials/hibernate-tutorials/

Cascade  (cascade = CascadeType.ALL) All means everything includes save, create, delete, update: If you have a parent and child objects, if you use cascade saving parent object will save the child objects with in the parent as well.

cascade=”delete-orphan” : delete-orphan allow parent table to delete few records (delete orphan) in its child table. Good to have cascade="delete-orphan"

The cascade=”delete” is declared in ‘stockDailyRecords’ to enable the delete cascade effect. When you delete the ‘Stock’, all its reference ‘stockDailyRecords’ will be deleted automatically

Hibernate interceptors : http://www.mkyong.com/hibernate/hibernate-interceptor-example-audit-log/
Interceptors : If we hibernate save onSave we can call method and we can do something. onDelete we can call method and we can do something. When the operation get performed we can intercept and ask the method to do some action.


fetch = FetchType.LAZY - 
Lazy - Defines that data can be lazily fetched
Eager - Defines that data must be eagerly fetched
Lazy will make object lighter. It's like a proxy. When the get method called it will hit db and fetch the record.
Eager - Eager will have the data already in the object. If you want to avoid the database hit use Eager. Otherwise, lazy. For small objects use eager. Big objects use lazy

HQL - Hibernate Query Language. Its same as SQL. HQL uses class name instead of table name, and property names instead of column name.

In HQL, only the INSERT INTO … SELECT … is supported; there is no INSERT INTO … VALUES. HQL only support insert from another table. For example
"insert into Object (id, name) select oo.id, oo.name from OtherObject oo";
Insert a stock record from another backup_stock table. This can also called bulk-insert statement.
Query query = session.createQuery("insert into Stock(stock_code, stock_name)" +
       "select stock_code, stock_name from backup_stock");
int result = query.executeUpdate();

Hibernate parameter binding examples

Always bind a parameter. Never concatenate the parameter on HQL. Concat is bad code. User can given anything as input and its SQL Injection may happen.
Named parameters
Parameter for the HQL is passed with property name with colon (:property_name)
Ex query : 
Query query = session.createQuery("From Employee WHERE departmentName=:dName");
query.setParameter("dName", "Marketing");
In setParameter you need to pass the named parameter as key.
setParameter - smart enough to discover the parameter data type for you 
setString - You can use setString if you know its a string
setProperties - you can pass object into the setProperties. Based on the parameter propertyName hibernate identifies it
Positional parameters
It’s use question mark (?) to define a named parameter, and you have to set your parameter according to the position sequence. See example…
String hql = "from Stock s where s.stockCode = ? and s.stockName = ?";
List result = session.createQuery(hql)
.setString(0, "7277")
.setParameter(1, "DIALOG")
.list();
Hibernate Transaction - You can rollback or commit the changes with hibernate
Hibernate Native SQL - You can use SQL directly using hibernate
Hibernate Named Query - You can declare the HQL with Name and you can use it across the class


Hibernate Performance tweaks:
dynamic-insert = true - Default is false. Dynamic insert true will make you insert only the object data which  exist values. Null values will not be constructed to insert into db. Make show_sql true to   see it.
dynamic-update = true - Default is false. Dynamic update true will update only the records you updating in the object rather getting saved the whole object data. 
invert="true" : (inverse - Opposite) : If you have parent and child objects, if you use inverse="true" saving parent object will not save child object with in the parent.


mutable="true" : We can change mutable as "false" it means the updates to this class will be ignored, but no exception is thrown, only the add and delete operation are allow. Mutable in collection add and delete-orphan are not allow in this collection, with exception throw, only update and ‘cascade delete all’ are allow. 


get and Load - Load will give the object with proxy (hibernate term) with data. It will not hit the db. IF the object not found you get NPE. 
get - It will hit the db and fetch the data. If data not exist null will be there.


Use Fetching strategies if you have parent child objects (http://www.mkyong.com/hibernate/hibernate-fetching-strategies-examples/
1. fetch-”join” = Disable the lazy loading, always load all the collections and entities.
2. fetch-”select” (default) = Lazy load all the collections and entities.
3. batch-size=”N” = Fetching up to ‘N’ collections or entities, *Not record*.
4. fetch-”subselect” = Group its collection into a sub select statement.


softDelete - 


How to auto create hbm files, java files and DAO files.

Provide this link in Eclipse->Help->Install New Software. Add it and install. So, all the dependencies will also get installed : http://download.jboss.org/jbosstools/updates/development/indigo/
Open a workspace for Hibernate Auto generation of hbm, java and DAO's.
Create a JAVA project with the ProjectName (Student | HibernateTool)
Windows -> Open Perspective -> Other -> select `Hibernate`
Write click in Hibernate explorer and click 'Add Configuration'
Click New on 'Database Connection'. Add a database connection (ex : mysql ). Go Next and add a Driver (JDBC Driver) based on the mysql connector java jar version you have. Remove the default jar. Add the jar and create driver and connection. Test the Connection with databasename to check all is well.
In the configuration point the directory under Project.
You can see all the database with data imported into your box.
Select `Hibernate code Generation Configuration` 
Click 'New' 
Select console configuration. Output Directory. Check 'Reverse Engineer from JDBC Connection'. Provide package name. Select 'reveng.xml new'.
In Exporter select 'Domain Code, .hbm.xml, Run.
Select hibernate in console configuration. 
Under project you can see the hbm and Domain Objects.


one_to_many

Always one will lend to many.
 
Hibernate Performance BottleNecks on Bulk Insert:
  
 
 Hibernate is problematic when you do bulk insert. You should use JDBC to avoid.
Bulk inserts of data are a type of operation best not performed by
Hibernate. For example, a user may have 100,000 records that have to be imported
into a single table. Don't use Hibernate for this sort of
operation—use your database's built-in import tools instead. The
built-in import will be faster than Hibernate (or, for that matter, handwritten
JDBC). 
 
MySQL Dialect doesn't support sequences. It supports only identity. identity makes hibernate not to work on bulk_insert.


If, for some reason, you do need to do a bulk import via Hibernate, take
account of the following tips:
  • Make sure the hibernate.jdbc.batch_size option (specified in your hibernate.properties, as described in Chapter 6) is turned on and set to a reasonably large value.
  • Consider Session.commit() on to break up the transactional overhead. Presumably you will do this only if you are very confident that it will succeed.
  • Make sure that you call Session.close() it or Session.clear() after each call to Session.commit(). Otherwise, Hibernate will attempt to maintain the inserted object in the session-level cache.
  • Consider the seqhilo (generator : hilo) or assigned generator to optimize key generation.

    Note :  Batch insert will be disabled if your auto generator value is based on mysql server and if mysql has to respond.

    Enable MySQL logs to see the queries :
    In MySQL prompt add below mysql>. Check 'show variables' to see earlier values
    SET global log_output = 'FILE';
    SET global general_log_file='/var/log/mysql.log';
    SET global general_log = 1;
     
    Note : Provide permission as "chown mysql:root " and "chmod 755 " for the same file.
    
    
    When you do bulk insert through webserver : 
    jdbc:mysql://dbserver/database?rewriteBatchedStatements=true&relaxAutoCommit=true

    Code : 
    try {
    autoCommit = getSession().connection().getAutoCommit();
    getSession().connection().setAutoCommit(false);
    Transaction tx = getSession().beginTransaction();
    for (MyObject object : objectList){
    getSession().saveOrUpdate(object);
    }
    tx.commit();
    }
    catch (.. ..){
    ...
    }

     
    Refer: http://upcom.eu/batch-inserts-in-hibernate/ 

No comments :

// Below script tag for SyntaxHighLighter