Introduction to Hibernate Java

Hibernate is a widely used open source software that provides object-relational mapping (ORM) solution for the Java language. It provides an easy to use framework for mapping an object-oriented domain model to a traditional relational database. It eases the work of application developer by generating the database code so developer does not have to handle relational data persistence-related programming tasks.

Java Persistence with Hibernate

Java provides JDBC to work with databases but the problem is that it requires developer to write SQL code for the database
exposes the data model to the application code. A better approach is to use Hibernate which takes care of SQL coding itself. You have to do mapping to let framework know which application filed maps to which database field.

Hibernate Java Persistence

Hibernate provides persistence for Java objects. It uses reflections and has support for over 30 different database drivers. So you can use hibernate for persistence with all popular databases. It has a query language to access objects and this query language provides high performance and low resource contention.

Hibernate uses runtime reflection to determine persistent properties of classes. It uses a mapping property to generate database schema which is used and provide persistence.

Hibernate - Concurrency

Java Hibernate has two types of concurrenies, optimistic concurrency and pessimistic concurrency.

Hibernate ensures optimistic concurrency by directly using JDBC connections and JTA resources without adding any additional locking behavior. Hibernate does not lock objects in memory. The application can expect the behavior as defined by the isolation level of the database transactions.
Thanks to the Session, which is also a transaction-scoped cache, Hibernate provides repeatable reads for lookup by identifier and entity queries (not reporting queries that return scalar values).

Hibernate ensures pessimistic concurrency by using an API for pessimistic locking of rows, using the SELECT FOR UPDATE syntax.

Hibernate – Optimistic Cocurrency

The only approach that is consistent with high concurrency and high scalability is optimistic concurrency control with versioning. Version checking uses version numbers, or timestamps, to detect conflicting updates (and to prevent lost updates). Java Hibernate provides 3 ways to write application code that uses optimistic concurrency. The following example shows one of them (Detached objects and automatic versioning):

Example:

Java Code:
Session session = sessionFactory.openSession();

// First Tx (read)
Transaction tx = session.beginTransaction();
myDataObj = session.get( ... );
tx.commit();
session.disconnect();

// ... User interaction ...
// Second Tx (write)
session.reconnect();

try {

   tx = session.beginTransaction();
   
   // myDataObj up-to-date?
   session.lock( myDataObj, LockMode.READ );
   myDataObj.setProperty( ... );
   tx.commit();

} catch( Exception ex ) {

if( tx != null ) tx.rollback();
   throw ex;
} finally {
   session.close();
}
Hibernate – Pessimistic Concurrency

Java Hibernate provides pessimistic concurrency to lock record for a process on the database. Pessimistic concurrency is only possible inside one database-transaction. A pessimistic lock can be requested using following methods:

  • Session.load(Class, id, LockMode)
  • Session.lock(Object, LockMode)
  • Query.setLockMode(alias, LockMode)


LockMode can be one of the following:

  • NONE
  • READ
  • WRITE
  • UPGRADE
  • UPGRADE_NOWAIT


Locks are realized on the database using variants of SELECT FOR UPDATE.

Hibernate Java – Example

To understand the concept, lets take an example. Consider an office environment where each employee has some boss and there is one employee who has no boss (the real boss). In software terms, we will represent this with one class called employee. The class has one attribute called name of type String and the relationship is self relationship and its Many to one. That is, many employees can have one boss.


´
Java class for employee will be:

Java Code:
package java_hybernate;

public class Employee
{
	private Long id; 
        private String name;
	private Employee boss;
	
        protected Employee() {} // Hibernate requires this
	
        public Employee(String name) {
		this.name = name;
	}

	public Long getId() {
		return id;
	}

	private void setId(Long id) {
		this.id = id;
	}

	public String getName() {
		return name;
	}

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

	public Employee getBoss() {
		return boss;
	}

	public void setBoss(Employee boss) {
		this.boss = boss;
	}
}
The above class ‘Employee’ is quiet simple. I declared private variables and their getters and setters. Obviously getters and setter are public. This to note is I created a variable called ‘boss’ of type Employee. It will hold the object pointing to the boss of an employee. We also have getter and setter for ‘boss’.

Beforing start persisting data using Hibernate Java, you must initialize Hibernate’s runtime environmsnt using:

Java Code:
// Import Statements
import org.hibernate.*;
import org.hibernate.cfg.*;
...
// And then inside your class
// Looks for mapping files in same classpath location as class
Configuration cfg = new Configuration()
.addClass(hello.Employee.class);
// This binds you to a database configuration
SessionFactory _sessions = cfg.buildSessionFactory();

Hibernate Java – Example (Operations)

Consider the above employee example. We want to create and save an employee in the database using Hibernate.

Java Code:
// Open a Session and a Transaction
Session session = _sessions.openSession();
Transaction trans = session.beginTransaction();
Employee emp = new Employee("Dave Morris");
session.save(emp);
// Flush all
trans.commit();
session.close();
Now we want to retrieve all the employees. We will print the number of employees, along with their names. Iterator is used to go through each employee.

Java Code:
import java.util.List;
import java.util.Iterator;
...
List employees = session.createQuery(
"from Employee emp order by emp.name asc").list();
System.out.println(employees.size() + " employee(s) found:");
for(Iterator iter=employees.iterator(); iter.hasNext(); ) {
Employee e2 = (Employee)iter.next();
System.out.println(e2.getName());
}
...
We want to modify an employee using Hibernate Java. Its also easy. We have to provide the primary key of employee whose name is to be changed.

Java Code:
...
Employee emp = (Employee)session.load(Employee.class, Long.valueOf("1"));
emp.setName("Imran Khan");
// Commit Transaction
...
We now want to delete an employee using Hibernate Java. We have to provide the primary key of employee whose name is to be changed (as we did while modifying an employee.

Java Code:
...
Employee emp = (Employee)session.
load(Employee.class, Long.valueOf("1"));
session.delete(emp);
// Commit Transaction
...
Hibernate Java will generate the SQL code of creating, saving, editing, removing and viewing employees itself.

Hibernate Annotations and Java Persistence API

Working with Hibernate, we commonly face problems with hbm.xml files. Hand-writing of the hbm.xml files is error prone. Other problems are synchronization of Java- and Mapping-Files is difficult and also readability of Mapping-Files is very poor. The solution to this is usage of Hibernate annotations. Hibernate Annotations are an implementation of the Java Persistence API (JPA).



Information about the mapping is integrated into the java files.

One important point to note is that do import javax.persistence.*, which Java Persistence Api otherwise the compiler will fail.

Example of Hibernate Annotations and Java persistence

Java Code:
package hello;

import javax.persistence.*;
@Entity
@Table(name = "EMPLOYEE")
public class Employee {
private Long id; private String name;
private Employee boss;
protected Employee() {}
public Employee(String name) {
this.name = name;
}
@Id @GeneratedValue
@Column(name = "ID")
public Long getId() {
return id;
}
private void setId(Long id) {
this.id = id;
}
@Column(updatable = true, name = "NAME", nullable = false, length = 50)
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@ManyToOne( cascade = {CascadeType.PERSIST, CascadeType.MERGE} )
@JoinColumn(name="BOSS_ID")
public Employee getBoss() {
return boss;
}
public void setBoss(Employee boss) {
this.boss = boss;
}
}
Following are important points and should be considered before using Hibernate Annotations and Java persistence:

  • Integrate the necessary jar-Files (from the Hibernate Annotation Package) into the CLASSPATH
  • Delete all mapping files that are obsolete now (i.e. Employee.hbm.xml)
  • Create a hibernate configuration-file hibernate.cfg.xml and put it in the directory where the hibernate.properties resides


This example file specifies all classes for Hibernate that are annotated:

hibernate.cfg.xml

Java Code:
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<mapping package="hello"/>
<mapping class="hello.Employee"/>
...
</session-factory>
</hibernate-configuration>
Another additional step before using hibernate annotations and Java Persistence is to adjust the initialization of the Hibernate runtime-environment.

Consider the example for the initialization of the Hibernate runtime-environment using Annotations.

Instead of following:

Java Code:
Configuration cfg = new Configuration().addClass(hello.Employee.class);
SessionFactory _sessions = cfg.buildSessionFactory();
Use this:

Java Code:
SessionFactory _sessions = new AnnotationConfiguration().configure().buildSessionFactory();
Java Annotations and Java Persistence – Comparison

Java persistence has a very important role in Hibernate. Lets talk about the benefits and drawbacks of Java Persistence.

Advantage of Java Persistence (JPA)

  • No additional mapping-files
  • Simple annotations instead of complex XML-files


Disadvantages of Java Persistence (JPA)

  • When the entities are used on client-side, all the JAR-files are necessary on the client (dependencies through the imports)


Java Hibernate Validator

Following the DRY (Don't Repeat Yourself) principle, Hibernate Validator let's you express your domain constraints once (and only once) and ensure their compliance at various level of your system automatically. Annotations are a very convenient and elegant way to specify invariant constraints on the domain model implementation, the persistent classes. Hibernate Validator comes bundled with a set of common validations, and you can build you own validation rules very easily.

Example:

Java Code:
public class Address {
@NotNull private String line1;
private String line2;
private String zip;
private String state;
@Length(max = 20)
@NotNull private String country;
@Range(min = -2, max = 50,
message = "Floor out of range")
public int floor;
...
}
Java Hibernate built-in constraints

Following are Java Hibernate built-in constraints that can be used according to the requirement.


@Length(min=, max=) --- check if the string length match the range
@Max(value=) --- check if the value is less than or equals to max
@Min(value=) --- check if the value is more than or equals to min
@NotNull --- check if the value is not null

@NotEmpty --- check if the string is not null nor empty. Check if the connection is not null nor empty
@Past --- check if the date is in the past
@Future --- check if the date is in the future
@Range(min=, max=) --- check if the value is between min and max (included)
@Size(min=, max=) --- check if the element size is between min and max (included)
@AssertFalse --- check that the method evaluates to false (useful for constraints expressed in code rather than annotations)
@AssertTrue --- check that the method evaluates to true (useful for constraints expressed in code rather than annotations)
@Valid --- perform validation recursively on the associated object. If the object is a Collection or an array, the elements are validated recursively. If the object is a Map, the value elements are validated recursively.
@Email --- check whether the string is conform to the email address specification
@CreditCardNumber --- check whether the string is a well formatted credit card number (derivative of the Luhn algorithm)
@Digits --- check whether the property is a number having up to integerDigits integer digits and fractionalDigits fractonal digits
@EAN --- check whether the string is a properly formatted EAN or UPC-A code
@Digits --- check whether the property is a number having up to integerDigits integer digits and fractionalDigits fractonal digits


Hibernate Annotations will translate the defined constraints for the entities into mapping metadata. For example, if a property of an entity is annotated @NotNull, its columns will be declared as not null in the DDL schema generated by Hibernate.

You can write your own validator, though its complex.

Hibernate Java – Logging

Logging is very important these days. Suppose you developed an application and it passed all the tests and was delivered to the client. Now, after few weeks he reported that the application crashed while working. How you will know what caused that crash? You have to spend many hours even days trying to figure that caused that failure. If you had enabled logging, you could simple read log files and track the problem area.

Hibernate Java uses Log4J for logging.

Log4j is an OpenSource logging API developed under the Jakarta Apache project. Log4j is widely used for logigng purpose because it is fully configurable, robust, reliable, easily extendible, and easy to implement framework. It helps debugging and monitoring Java applications. Lot of online material is available which can help newbies in getting familier with this.

To enable this, create a file called log4j.properties and put it in the same directory like the hibernate.properties.


Example:

log4j.properties

# Direct log messages to stdout
log4j.appender.stdout=org.apache.log4j.ConsoleAppe nder
log4j.appender.stdout.Target=System.out
log4j.appender.stdout.layout=org.apache.log4j.Patt ernLayout
# Root logger option
log4j.rootLogger=INFO, stdout
# Hibernate logging options
log4j.logger.org.hibernate=INFO
# Log JDBC bind parameter runtime arguments
log4j.logger.org.hibernate.type=INFO

Java Hibernate Tools

You can use following tools for Hibernate:
  • Eclipse Integration (i.e. XML-support)
  • DDL schema generation from a mapping file (hbm2ddl)
  • Java source generation from a mapping file (hbm2java)


Middlegen (mapping file generation from an existing database schema) is a third party tool that can be used for Hibernate.