Search This Blog

Sunday 11 September 2011

Id Generators - 1

Most tables we create in the database have primary keys. The mapping classes that we create in java include the <id> or <composite-id> attribute to map the primary key.
In case of the <id> attribute, hibernate provides an optional  <generator> element that is used to manage the creation of id values for new records inserted in tables. The generator class actually includes a class attribute which specifies the class (and therefore the technique) used to generate primary keys.
Users have the option to use one of these methods or to go in for their own custom implementations. These generator classes have been provided with shortcut names.
  1. sequence
  2. identity
  3. hilo
  4. seqhilo
  5. native
  6. increment
  7. foreign
  8. guid
  9. select
  10. assigned
  11. uuid.hex
Let us look at these through examples: sequence
In this generator type, the primary key is based on a sequence defined in the database.
Mapping file:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.model">
    <class name="SequencedUnit" table="SEQUENCED_UNIT">
        <id name="id" type="integer">
            <column name="ID" />
            <generator class="sequence">
                <param name="sequence">simple_id_seq</param>                
            </generator>
        </id>
        <property name="name" type="string">
            <column name="NAME" />
        </property>

    </class>
</hibernate-mapping>
As seen above the generator class has been defined with type sequence. In the case the name of the sequence is provided in the nested <param> element.
The Java Class:
package com.model;

public class SequencedUnit {
    private Long id;
    private String name;
    //setter getters
   
}


The sequence simple_id_seq needs to be created in the database. When the object is saved from java the database retrieves the next number from sequence and inserts it as the primary key. The value is also returned to the java class and set in the id property of the saved object.

NOTE: This class is not supported for MySql database.

identity :

This is used with identity columns present in the database

 Mapping file:
<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN"
"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="com.model">
    <class name="Person" table="PERSON">
        <id name="id" type="integer" column="ID" >
        <generator class="identity"/> 
        </id>
        
        <property name="name" type="string">
            <column name="NAME" />
        </property>
        <property name="age" type="integer">
            <column name="AGE" />
        </property>
    </class>
</hibernate-mapping> 


the Java class:

The java class is a simple POJO.
package com.model;

public class Person {
    private Integer id;
    private String name;
    private Integer age;
   //setter getters
    
}
The actual db SQL:
create table PERSON  (
  ID int(11) not null auto_increment,
  NAME varchar(100) not null,
  AGE int(11) not null,
  PRIMARY KEY (ID)
  );


On executing the code to create a database record the logs are below:
Person p = new Person();
p.setAge(12);
p.setName("IdentityUser");
Session session = sessionFactory.openSession();
Transaction transaction = session.beginTransaction();
session.save(p);
transaction.commit();
 

2578 [main] DEBUG org.hibernate.jdbc.JDBCContext  - after transaction begin
2594 [main] DEBUG org.hibernate.event.def.DefaultSaveOrUpdateEventListener  - sa
ving transient instance
2594 [main] DEBUG org.hibernate.event.def.AbstractSaveEventListener  - saving [c
om.model.Person#<null>]
2594 [main] DEBUG org.hibernate.event.def.AbstractSaveEventListener  - executing
 insertions
2609 [main] DEBUG org.hibernate.event.def.AbstractSaveEventListener  - executing
 identity-insert immediately
2609 [main] DEBUG org.hibernate.persister.entity.AbstractEntityPersister  - Inse
rting entity: com.model.Person (native id)
2609 [main] DEBUG org.hibernate.jdbc.AbstractBatcher  - about to open PreparedSt
atement (open PreparedStatements: 0, globally: 0)
2609 [main] DEBUG org.hibernate.SQL  - insert into PERSON (NAME, AGE) values (?,
 ?)
2609 [main] DEBUG org.hibernate.jdbc.AbstractBatcher  - preparing statement
2656 [main] DEBUG org.hibernate.persister.entity.AbstractEntityPersister  - Dehy
drating entity: [com.model.Person#<null>]
2656 [main] DEBUG org.hibernate.type.StringType  - binding 'IdentityUser' to par
ameter: 1
2656 [main] DEBUG org.hibernate.type.IntegerType  - binding '12' to parameter: 2
2656 [main] DEBUG org.hibernate.id.IdentifierGeneratorFactory  - Natively genera
ted identity: 4 
As can be seen from above logs Hibernate detected the id generator class and used the id provide by the database to update the id field. The id is returned as a part of the insert call (java.sql.Statement.getGeneratedKeys() method) and set in the just saved object

No comments:

Post a Comment