How to generate Custom Id using hibernate while it must be primary key of table
The best way to implement custom id generator in Hibernate.
@Entity
@Table(name = "employee_customid")
public class Employee implements Serializable {
@Id
@GenericGenerator(name = "string_based_custom_sequence", strategy =
"com.ie.customid.EmployeeIdGenerator")
@GeneratedValue(generator = "string_based_custom_sequence")
@Column(name = "custom_emp_id")
private String id;
@Column(name = "emp_name")
private String name;
@Column(name = "emp_age")
private Integer age;
@Column(name = "emp_salary")
private Double salary;
// getter setter and toString
Below code is implementation for generating custom id in hibernate with any database code will be same (with minimal changes)
package com.ie.customid;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.id.IdentifierGenerator;
import java.io.Serializable;
import java.sql.Connection;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.sql.Statement;
public class EmployeeIdGenerator implements IdentifierGenerator {
//You can give any name to sequence be sure that you know how to use it.
private final String DEFAULT_SEQUENCE_NAME = "hibernate_sequence";
//private final String DEFAULT_SEQUENCE_NAME = "hib_sequence";
/*
* This method will generate custom id based on String followed by id
* e.g. emp0001, emp0002, emp0003 and so on..
* */
public Serializable generate(SessionImplementor session, Object object) throws HibernateException {
Serializable result = null;
Connection connection = null;
Statement statement = null;
ResultSet resultSet = null;
String prefix = "emp";
try {
connection = session.connection();
statement = connection.createStatement();
try {
/*
* uncomment below line if you are using mysql and the sequence DOES NOT EXIST.
* As we all know MySql does not support sequence, instead there is AUTO INCREMENT
* if you are using other databases change SQL according to that
* e.g. Oracle: "SELECT "+sequenceName+".NEXTVAL FROM DUAL"
* PostgreSQL: "SELECT NEXTVAL('+sequenceName+"')
* */
//statement.executeUpdate("UPDATE " + DEFAULT_SEQUENCE_NAME + " SET next_val=LAST_INSERT_ID(next_val+1)");
resultSet = statement.executeQuery("SELECT next_val FROM " + DEFAULT_SEQUENCE_NAME);
} catch (Exception e) {
System.out.println("In catch, cause : Table is not available.");
// if sequence is not found then creating the sequence
// Below code is for MySql database you change according to your database
statement.execute("CREATE table " + DEFAULT_SEQUENCE_NAME + " (next_val INT NOT NULL)");
statement.executeUpdate("INSERT INTO " + DEFAULT_SEQUENCE_NAME + " VALUES(0)");
//==> LAST_INSERT_ID(next_val+1) -> this is inbuilt function of MySql so by using this we can achieve our custom sequence like auto increment
statement.executeUpdate("UPDATE " + DEFAULT_SEQUENCE_NAME + " SET next_val=LAST_INSERT_ID(next_val+1)");
resultSet = statement.executeQuery("SELECT next_val FROM " + DEFAULT_SEQUENCE_NAME);
//e.printStackTrace();
}
if (resultSet.next()) {
int nextValue = resultSet.getInt(1);
String suffix = String.format("%04d", nextValue);
result = prefix.concat(suffix);
System.out.println("Custom generated sequence is : " + result);
}
} catch (SQLException e) {
e.printStackTrace();
}
return result;
}
}
If you like to use XML configuration then use below code
<?xml version='1.0' encoding='UTF-8'?>
<!DOCTYPE hibernate-configuration PUBLIC
"-//Hibernate/Hibernate Configuration DTD 3.0//EN"
"http://www.hibernate.org/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
<session-factory>
<property name="hbm2ddl.auto">update</property>
<property name="dialect">org.hibernate.dialect.MySQLDialect</property>
<property name="connection.url">jdbc:mysql://localhost:3306/Testing</property>
<property name="connection.username">root</property>
<property name="connection.password">root</property>
<property name="show_sql">true</property>
<property name="format_sql">true</property>
<property name="connection.driver_class">com.mysql.jdbc.Driver</property>
<mapping class="com.ie.entity.Employee"/>
<!-- uncomment below line if you want to use XML based mapping & NOTE : if you will use both then XML will override annotation -->
<!-- <mapping resource="Employee.hbm.xml"></mapping>-->
</session-factory>
</hibernate-configuration>
Below is Employee mapping file
<?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 name="com.ie.entity.Employee" table="employees_customid">
<id name="id" column="employeeId">
<generator class="com.ie.customid.EmployeeIdGenerator"/>
</id>
<property name="name" column="e_name"></property>
<property name="age" column="e_age"/>
<property name="salary" column="e_salary"/>
</class>
</hibernate-mapping>
Thank you everyone for your response...... finally i have done some changes in my Department class and used a class for generating ids........Here is my code
@Entity
public class Department {
@Id
@GenericGenerator(name = "sequence_dep_id", strategy = "com.xyz.ids.DepartmentIdGenerator")
@GeneratedValue(generator = "sequence_dep_id")
@Column(name="Department_Id")
private String deptId;
@Column(name="Department_Name",unique=true,nullable=false)
private String deptName;
@Column(name="Department_Description")
@NotNull
private String deptDesc;
//getters and setters
DepartmentIdGenerator.java
package com.xyz.ids;
import java.io.Serializable;
import java.sql.*;
import org.hibernate.HibernateException;
import org.hibernate.engine.spi.SessionImplementor;
import org.hibernate.id.IdentifierGenerator;
public class DepartmentIdGenerator implements IdentifierGenerator{
@Override
public Serializable generate(SessionImplementor session, Object object)
throws HibernateException {
String prefix = "DEP";
Connection connection = session.connection();
try {
Statement statement=connection.createStatement();
ResultSet rs=statement.executeQuery("select count(Department_Id) as Id from demo.Department");
if(rs.next())
{
int id=rs.getInt(1)+101;
String generatedId = prefix + new Integer(id).toString();
System.out.println("Generated Id: " + generatedId);
return generatedId;
}
} catch (SQLException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return null;
}
}