Knowingly or unknowingly, we have been using generator classes in hibernate since our first basic hibernate application. In this tutorial, we are going to see what are hibernate generator classes and their uses.
Hibernate Generator Classes :
Generators are one of the most key concepts in hibernate. Hibernate provides different types of predefined generator classes, to represent a primary key in the database.
A generator class is used to generate an Id for an object, which is going to be inserted in the database as a primary key.
Predefined Generator Classes :
To generate the primary key, hibernate uses generators. Below are the different types of predefined generator classes in hibernate.
Hibernate has given some predefined generator classes listed below.
- assigned
- increment
- sequence
- hilo
- identity
- native
- foreign
- uuid
The above classes are some of the important predefined generator classes in hibernate.
If your requirement doesn’t satisfy the above all generators, don’t worry! We can also implement our own generator classes in hibernate.
How to use Hibernate Generator classes?
We can use all possible generator classes in our application as per our requirement. Hibernate provides a <generator> tag to represent the generator. However, it is a sub-element of <id>. We have to define these elements in the mapping file, i.e. (hbm.xml) to represent an Id property of Plain Old Java Object(POJO) class.
Hibernate provides a shortcut name for each predefined generator class so that the <generator> tag have to configure with this shortcut name.
Below is the detailed usage of every generator class in hibernate.
assigned generator:
The assigned generator is the default generator. If we forgot to configure the generator class, hibernate by default consider assigned as a generator and assigned is a shortcut name given for the Assigned class.
The assigned class returns the same id set by the programmer to hibernate and hibernate will store an object with that id in the database.
<id name="studentId" column="sid">/>
OR
<id name="studentId" column="sid">
<generator class="assigned"/>
</id>
On the above example, both syntaxes are same for the assigned generator. We can use either of them.
increment generator :
An increment is a shortcut name for IncrementGenerator class. When we configure the generator class as increment, the IncrementGenerator class reads the max value of the existing ids in the database table and then increments it by one and returns the id value to hibernate.
Formula : max(id)+1
<id name="studentId" column="sid">
<generator class="increment"/>
</id>
Increment Generator Example :
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://www.hibernate.org/dtd/hibernate-mapping-3.0.dtd">
<hibernate-mapping>
<class catalog="onlinetutorialspoint" name="com.onlinetutorialspoint.pojo.Student"
table="student">
<id name="studentId" column="sid">
<generator class="increment" />
</id>
<property name="name" type="string">
<column length="50" name="name" />
</property>
<property name="rollNumber" type="java.lang.Integer">
<column name="rollnumber" />
</property>
</class>
</hibernate-mapping>
Client class:
package com.onlinetutorialspoint.service;
import com.onlinetutorialspoint.pojo.Student;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.hibernate.Transaction;
import org.hibernate.cfg.Configuration;
public class Main {
public static void main(String[] args) {
Configuration configuration = new Configuration();
configuration.configure("hibernate.cfg.xml");
SessionFactory factory = configuration.buildSessionFactory();
Session session = factory.openSession();
Transaction tx = session.beginTransaction();
Student student = new Student();
student.setName("chandrashekhar");
student.setRollNumber(007);
session.save(student);
tx.commit();
session.close();
}
}
Output:
INFO: Envers integration enabled? : true
Hibernate: select max(id) from student
Hibernate: insert into onlinetutorialspoint.student (name, rollnumber, id) values (?, ?, ?)
By observing the above output, hibernate first get the max(id) from the database after executing the insert command.
When we use this increment generator, if an id is set by the programmer for an object, it will not be considered by the hibernate.
sequence generator :
The sequence is a shortcut name for SequenceGenerator class. It reads next value of a database sequence and then returns that value as id to the hibernate.
To use this sequence generator in hibernate configuration file (hbm.xml) we need to configure the database sequence name as a parameter to the SequenceGenerator class.
We can create a sequence in the database by using the below syntax :
create sequence <sequence name> start with <Number> increment by <Number>;
Example :
create sequence mysequence start with 1 increment by 1;
Hibernate hbm.xml :
<id name="studentId" column="sid">
<generator class="sequence">
<param name="sequence">mysequence</param>
</generator>
</id>
As shown above we can use the database sequences in hibernate.
What happens when no sequence name is mentioned?
If we do not configure a database sequence name as a parameter, then SequenceGenerator class creates its own sequence with the name hibernate_sequence. After that, it reads the next value of that sequence.
If SequenceGenerator class created by its own sequence called hibernate_sequence, then it will set the default behaviour as start with 1 and increment by 1.
Note: Sequence is a Database dependent of the generated class. For example, the sequence generator can be used in Oracle database, but it can not be used in MySQL Database.
hilo generator :
hilo is a shortcut name for TableHiloGenerator class. It is something different when compared to other generator classes. Let us see how it differs with others.
When we configure Hilo generator class in the hbm.xml file, along with the generator name we can pass three parameters :
- table
- column
- max_lo
Syntax :
<id name="studentId" column="sid">
<generator class="hilo">
<param name="table">mytable</param>
<param name="column">col1</param>
<param name="max_lo">10</param>
</generator>
</id>
If we do not configure the above three parameters, then hibernate will give the default values to them as :
- table : hibernate_unique_key
- column : next_hi
- max_lo : 32767
hilo generator follows a formula to generate Id. It always generates the first id as “1”, from the next Id onwards it will apply formula.
Hilo generator formula :
max_lo * next_hi +next_hi
By taking the given parameters, hilo will create a table with one column and calculate the column value based on the hilo formula.
Hilo Case Study :
Let us calculate the Id value for bellow parameters :
<id name="id" column="id" type="java.lang.Integer">
<generator class="hilo">
<param name="table">mytable </param>
<param name="column">col1 </param>
<param name="max_lo">10 </param>
</generator>
</id>
Here we took a table named as my table, column name as col1 and max_lo value is 10.
- When first-time hilo generator executed, then the id is ‘1’.
- Second time onwards hilo uses the formula for generating the Id. So by applying the above formula, the Id is “11”
max_lo * next_hi + next_hi
here, max_lo = 10 (in hbm.xml we configured)
next_hi = 1 (already existed value in the column col1)
then
10 * 1 + 1 = 11 and in the col1 it updates the value as “2” (Phase 2)
- For the third time, hilo generates id as “22”
10 * 2 + 2 = 22 and in the col1 it updates the value as “3” (Phase 3)
This is how hilo generator works. And hilo generator is database-independent generator, It will work on all databases.
identity generator :
identity is a shortcut name for IdentityGenerator class. It is a database dependent generator, i.e. it will work on some databases only, example it works on MySql, not in Oracle database.
<id name="studentId" column="sid">
<generator class="identity" />
</id>
When IdentityGenerator class is called, it reads an auto-incremented column algorithm of the database and take the auto-incremented value and returns it as id to hibernate.
As we discussed auto-incremented algorithm doesn’t exist in all the databases, hence identity generator is a database dependent generator. Identity generator works on MySQL database but doesn’t work on Oracle database because there is no autoincrement functionality in Oracle database.
native generator :
native is the shortcut name for NativeGenerator class. If we configure the generator as native, this behaviour varies from database to database.
<id name="studentId" column="sid">
<generator class="native" />
</id>
The native generator will first checks if the database supports the identity generator or not.
If the database supports identity generator, then it acts as identity.
If the database doesn’t support for identity, it will check for sequence generator.
If the database supports for sequence generator, then it acts as a sequence. Otherwise, if the database doesn’t support for the sequence, then it will act as hilo generator.
Since the hilo generator is database-independent, the native generator will act as hilo.
foreign generator :
foreign is a shortcut name for ForeignGenerator class. The ForeignGenerator is only applicable for one-one relationship.
<id name="studentId" column="sid">
<generator class="foreign" />
</id>
The ForeignGenerator class returns the id of the parent object as the id for the child object.
uuid generator :
Except for the assigned generator, remaining all generator classes discussed above will work for number type of primary key.
If a primary key of a table is string type then we can use assign generator or we can use another generator class uuid (Universal Unique Identifier) generator.
<id name="studentId" column="sid">
<generator class="uuid" />
</id>
uuid is a shortcut for AbstractUUIDGenerator class. uuid generator generates a string of 32 characters length based on the following four values:
- IP Address of the machine
- Start-up time of JVM
- System time
- Counter value in JVM
Based on the four values UUIDGenerator class generates a unique Identifier and returns to hibernate.
Though it is system generated or unique identifier, there is a problem with using this uuid generator. To load an object from the database we can use either get() or load() methods in hibernate. To load an object we need to pass parameters to get() or load() methods as :
get(Class class,Serializable id);
load(Class class,Serializable id);
To use the above two methods, we need to pass the primary key value of the table to get the details from the database. If the primary key id is generated by uuid generator, it will generate a string with 32 characters. As this is too long, it is not recommended to use. For this, we can go with custom generator classes.
Happy Learning 🙂