Search This Blog

Monday, 17 June 2013

JPA's GenerationType.TABLE

In the previous posts we saw the identifier generation strategies supported by JPA and their equivalent ones in Hibernate. There is however one in JPA - The TABLE GenerationType that is not there in Hibernate API. I decided to look at the same.
I took the same class from the previous post:
    public void setId(Long id) {
        this.id = id;
    }

    @TableGenerator(schema="firstOne", table = "ID_TABLE", name = "AppUserIdTable", 
        allocationSize = 1000, initialValue = 0, pkColumnName = "pk", 
        valueColumnName = "value", pkColumnValue = "app_user")
    @GeneratedValue(strategy = GenerationType.TABLE,generator="AppUserIdTable"))
    public Long getId() {
        return id;
    }

    @Column(name = "NAME")
    public String getName() {
        return name;
    }
        // other methods
}
This generator is somewhat similar to Hibernate's hilo strategy. As we saw for sequence GenerationType, here too there is an additional annotation to use - @TableGenerator
If we run the code, the DDL generated by Hibernate is as below:
create table firstOne.APP_USER (
        id int8 not null,
        NAME varchar(255),
        primary key (id)
    )
    create table firstOne.ID_TABLE (
         pk varchar(255),
         value int4 
    )
along with the owner table, Hibernate created an additional table. This table is like a multi-hilo table. The value column is the one that holds the next high value of the sequence. Every time the JPA provider needs to start creating User records, it will pick up the high value from here. This high value is used along with the allocationSize attribute to generate unique identifiers. Once the limit is reached a new value is retrieved from the database.
If we execute the insert code then the logs are as below:
2843 [main] DEBUG org.hibernate.event.def.DefaultPersistEventListener  - saving 
transient instance
2984 [main] DEBUG org.hibernate.id.MultipleHiLoPerTableGenerator  - new hi value
: 0
2984 [main] DEBUG org.hibernate.event.def.AbstractSaveEventListener  - generated
 identifier: 1, using strategy: org.hibernate.id.MultipleHiLoPerTableGenerator
3046 [main] DEBUG org.hibernate.SQL  - 
    insert 
    into
        firstOne.APP_USER
        (NAME, id) 
    values
        (?, ?)
As seen the value 0 was retrieved by Hibernate, the new id value generated was one and the record was saved. So how does this differ from the hilo strategy?
This is where the second column comes in. The second column is an id column that indicates which table the record is associated with? In our case the record with value "app_user" will indicate the next high value to be used for creating User records. For any other class, there would be a different entry.
Unlike the hilo strategy where we needed a separate table for every entity class, here we can use the same table for holding high values for multiple entities.
The schema attribute is needed for postgreSQL, else Hibernate will use the default schema.

No comments:

Post a Comment