-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 
Author Message
 Post subject: Implementing a custom unique random identity generator
PostPosted: Thu Aug 19, 2010 6:38 pm 
Beginner
Beginner

Joined: Tue Aug 03, 2010 4:32 pm
Posts: 22
Greetings,

All my data tables in my database have a BIGINT field named "id" as their pk.
NONE of them use the AUTO_INCREMENT feature - instead I have a table named
Used_Random_Longs consisting of fields:
--- random_long BIGINT(12) unsigned PRIMARY KEY,
--- used_in_table varchar(30)

Inserting a row into a data table consists of:
a--using a stored procedure to generate random BIGINTs until one
successfully INSERTs into UsedRandomLongs then returning
successfulbigint
b--insert the desired data into a new row of the data table then perform an
UPDATE UsedRandomLongs
SET used_in_table = datatablename
WHERE id = successfulbigint

Thus I can guarantee every id is unique across the database and know at a glance which table it's used in.

Now I'd like to build a custom identity generator to achieve the same thing.

So far I've got this
Code:
package dogs.model;

import org.hibernate.*;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.id.Configurable;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.dialect.Dialect;

import org.hibernate.type.Type;

import java.io.Serializable;
import java.sql.*;

import utils.*;

import static org.hibernate.criterion.Expression.*;

import java.util.*;

public class UniqueLongIdGenerator implements IdentifierGenerator
{

     public Serializable generate(SessionImplementor session, Object object) throws HibernateException
     {
       Long out_llng = -1L;
        UsedRandomLongs uri = null;

        Random rand_generator = new Random();
       
        do {
              out_llng = rand_generator.nextLong() & 0xE8D4A50FFF; // masks to 0 - 999999999999
              uri = new UsedRandomLongs();
        } while ( !session.save( uri, out_llng;
        return out_llng;
     }

}


and
Code:

package dogs.model;

import org.hibernate.*;
import org.hibernate.cfg.*;
import org.hibernate.Query;
import org.hibernate.context.ManagedSessionContext;
import javax.persistence.*;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;

import utils.*;

import java.util.Arrays;

@Entity
@Table(name="Used_Random_Longs")
public class UsedRandomLongs
{
    @Id
    @Column(name="random_long")
    private Long id;
    private String used_in_table;

    //constructor
    UsedRandomLongs() {
        this.used_in_table = "pending";
    }

    ........


and one class that's been mapped to a data table
Code:
package dogs.model;

import org.hibernate.*;
import org.hibernate.cfg.*;
import org.hibernate.Query;
import org.hibernate.context.ManagedSessionContext;
import javax.persistence.*;

import javax.faces.component.UIComponent;
import javax.faces.context.FacesContext;
import javax.faces.event.ActionEvent;

import utils.*;

import java.util.Arrays;

@Entity
@Table(name="Frogs")
public class Frogs
{
    @Id
    @GeneratedValue(generator="UniqueLongIdGenerator")
    @Column(name="random_integer")
    private Long id;

    ........


Any help/hints/suggestions/constructive criticisms and examples are all appreciated!


Still-learning Steve


Top
 Profile  
 
 Post subject: Re: Implementing a custom unique random identity generator
PostPosted: Mon Aug 23, 2010 6:44 pm 
Beginner
Beginner

Joined: Tue Aug 03, 2010 4:32 pm
Posts: 22
Hm, no takers. Allright let's make the problem simpler. My custom id generator now just spits out a random long

Code:
public class UniqueLongIdGenerator implements IdentifierGenerator, Configurable
{
   private String tableName;
   
   public void configure( Type arg0, Properties props, Dialect arg2 ) throws MappingException { 
       setTableName( props.getProperty( "tableName" ) ); 
   }

     public Serializable generate( SessionImplementor session, Object object) throws HibernateException
     {
         Long out_llng = -1L;
       
          Random rand_generator = new Random();
             
          return rand_generator.nextLong();

     }
     
     // getter & setter for the configurable parameters 
     public String getTableName() { 
         return tableName; 
     } 
     public void setTableName( String aa ) { 
         this.tableName = aa; 
     } 

}


and my entity class
Code:
@Entity
@Table(name="Logs")
public class Log
{
    @Id
    @GeneratedValue(generator="UniqueLongIdGenerator")
    @GenericGenerator(name="UniqueLongIdGenerator",
                    strategy="UniqueLongIdGenerator",
                    parameters = { @Parameter(name="tableName", value="Log")}
    )
    @Column(nullable=false)
    private Long id
    ....


I do have a <mapping class="foo.UniqueLongIdGenerator"/> statement in my hibernate.cfg.xml file.

When I try to execute the above I get the "unknown id.generator" error. What must I do/undo/modify to solve this? The manuals seem to be somewhat vague on the detaills of implementation.

TIA,

Still-learning Steve


Top
 Profile  
 
 Post subject: Re: Implementing a custom unique random identity generator
PostPosted: Tue Aug 24, 2010 12:05 am 
Beginner
Beginner

Joined: Tue Aug 03, 2010 4:32 pm
Posts: 22
Turns out the strategy parameter needs to be a fully qualified path to the class of the generator:

Code:
    @Id
    @GeneratedValue(generator="MyCustomGenerator")
    @GenericGenerator(name="MyCustomGenerator",
                    strategy="forests.model.UniqueLongIdGenerator",
                    parameters = { @Parameter(name="tableName", value="Log")}


So the simplified case works now, yea.


Top
 Profile  
 
 Post subject: Re: Implementing a custom unique random identity generator
PostPosted: Tue Aug 24, 2010 9:56 pm 
Beginner
Beginner

Joined: Tue Aug 03, 2010 4:32 pm
Posts: 22
I was able to solve the more complex problem by moving the generate-unique-random-bigint code into the database itself via a called stored procedure. This reduced the custom identity generator to:
Code:
public class UniqueLongIdGenerator implements IdentifierGenerator, Configurable
{
   private String tableName;
   
   public void configure( Type arg0, Properties props, Dialect arg2 ) throws MappingException { 
       setTableName( props.getProperty( "tableName" ) ); 
   }

     public Serializable generate( SessionImplementor session, Object object) throws HibernateException
     {
       Long out_llng = -1L;
       
       try {
            String sqlcmd = "{call get_random_bigint( ?, ?)}";
            Connection conn = session.connection();
            CallableStatement cs = conn.prepareCall( sqlcmd);
            //set input parameter
            cs.setString( 1, tableName);
            //set output parameter
            cs.registerOutParameter( 2, java.sql.Types.BIGINT);
            cs.execute();
            //exctract returned value
            out_llng = cs.getLong(2);
       } catch ( SQLException e) {
          System.out.println( "UhOh, " + e);   
       }

        return out_llng;
     }
     
     // getter & setter for the configurable parameters 
     public String getTableName() { 
         return tableName; 
     } 
     public void setTableName( String aa ) { 
         this.tableName = aa; 
     } 

}



So now in main() :
Code:
Log aLog = new Log();
sess.save(aLog);

has the effect of creating a new Log object with a random Long as an id and the id being guaranteed to be unique within the database by entering the row
random_bigint:'Logs'
into the UsedRandomInteger table

CASE CLOSED

Still-learning Steve


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 4 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.