30

Here is my pojo class

@Entity

public class Department {


@Id
@GeneratedValue(strategy=GenerationType.IDENTITY)

@Column(name="Department_Id")

private Integer deptId;


@Column(name="Department_Name",unique=true,nullable=false)
private String deptName;


@Column(name="Department_Description")
@NotNull
private String deptDesc;
   //geters and setters

What I want is that department_id must be primary key of this Department table and entries for this key must be as DEP0001, DEP0002,DEP0003

3

2 Answers 2

41

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;
    }

}
Sign up to request clarification or add additional context in comments.

8 Comments

eclipse complains about it saying no generator named <YOUR_GENERATOR> is defined in persistence unit
did you also defined it in persistence.xml or it is bug in eclipse?
The lack of this is when we delete one entry from the table and try to create new one. we can have a primary key constraint violation !
@sic-sic you are absolutely right. do you have any idea how to do it correctly.
You can use a "select max(Department_id)" instead of "select count(Departement_id)" if Department_id is a number type
|
6

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>

1 Comment

Incase anyone is doing the method suggested by Sumit , then you must remember to rollback the transaction in the inner catch block with connection.rollback() . The default behavior of PostgreSQL is to prevent a user from going forward with commits after even a single statement fails, so to bypass that, this statement is necessary.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.