Hibernate Books

All times are UTC - 5 hours [ DST ]



Post new topic Reply to topic  [ 4 posts ] 
Author Message
 Post subject: BigDecimalType is not handled in IdentifierGeneratorFactory
PostPosted: Tue Sep 05, 2006 6:48 pm 
Beginner
Beginner

Joined: Thu May 18, 2006 2:58 pm
Posts: 25
Please see here...http://opensource.atlassian.com/projects/hibernate/secure/IssueNavigator.jspa

BigDecimalType is not handled in IdentifierGeneratorFactory - this problem has been rejected.

I disagree with the resolution. BIGINTEGER in all the documentation is the recommended map for Oracle NUMBER. So it seems to me that when a sequence returns a number, it should be automatically converted to a BigInteger in IdentifierGeneratorFactory.

Seems to me that it should be a standard return type. Is there any way to re-review this?


Last edited by fischman_98 on Wed Sep 06, 2006 5:24 pm, edited 1 time in total.

Top
 Profile  
 
 Post subject: BigDecimalType is not handled in IdentifierGeneratorFactory
PostPosted: Wed Sep 06, 2006 5:18 pm 
Beginner
Beginner

Joined: Thu May 18, 2006 2:58 pm
Posts: 25
I am editing this post as I figure things out. It appears that the IdentifierGeneratorFactory that is used to get a sequence value will only return long, integer, short or string (see code below).

Is there any reason why it shouldn't return a BigInteger (which is what should be mapped with an Oracle NUMBER)?

A side question - Is there any reason Oracle NUMBER can't be mapped to long?

I am thinking of adding a line in the get method to return BigInteger.

Code:
public static Serializable get(ResultSet rs, Type type)
   throws SQLException, IdentifierGenerationException {
   
      Class clazz = type.getReturnedClass();
      if ( clazz==Long.class ) {
         return new Long( rs.getLong(1) );
      }
      else if ( clazz==Integer.class ) {
         return new Integer( rs.getInt(1) );
      }
      else if ( clazz==Short.class ) {
         return new Short( rs.getShort(1) );
      }
      else if ( clazz==String.class ) {
         return rs.getString(1);
      }
      else {
         throw new IdentifierGenerationException("this id generator generates long, integer, short or string");
      }
      
   }


-----
Original post
-----
I have a table with a number column

CREATE TABLE N_CUSTOMER (
CUSTOMER_ID NUMBER NOT NULL,

POJO code:

public class NCustomer {

private BigInteger customerId;

Mapping:

<class name="NCustomer" table="N_CUSTOMER" optimistic-lock="none">
<id name="customerId" type="big_integer" unsaved-value="null">
<column name="CUSTOMER_ID" not-null="true" precision="22" scale="0"/>
<generator class="sequence">
<param name="sequence">SEQ_N_CUSTOMER</param>
</generator>
</id>

I have a sequence that returns a customer id (see error below). Do I need to create a Custom Mapping to convert the sequence value returned to a BigInteger?

With the log set to debug, I receive the following error on a save.
Code:
18:42:39,701 DEBUG SQL:346 - select IRMAIR.SEQ_N_CUSTOMER.nextval from dual
Hibernate: select IRMAIR.SEQ_N_CUSTOMER.nextval from dual
org.hibernate.id.IdentifierGenerationException: this id generator generates long, integer, short or string
   at org.hibernate.id.IdentifierGeneratorFactory.get(IdentifierGeneratorFactory.java:59)
   at org.hibernate.id.SequenceGenerator.generate(SequenceGenerator.java:78)
   at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId(AbstractSaveEventListener.java:91)
   at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:186)
   at org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId(DefaultSaveEventListener.java:33)
   at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:175)
   at org.hibernate.event.def.DefaultSaveEventListener.performSaveOrUpdate(DefaultSaveEventListener.java:27)
   at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.onSaveOrUpdate(DefaultSaveOrUpdateEventListener.java:70)
   at org.hibernate.impl.SessionImpl.fireSave(SessionImpl.java:530)
   at org.hibernate.impl.SessionImpl.save(SessionImpl.java:518)
   at org.hibernate.impl.SessionImpl.save(SessionImpl.java:514)
   at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
   at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source)
   at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source)
   at java.lang.reflect.Method.invoke(Unknown Source)
   at org.hibernate.context.ThreadLocalSessionContext$TransactionProtectionWrapper.invoke(ThreadLocalSessionContext.java:301)
   at $Proxy0.save(Unknown Source)


Top
 Profile  
 
 Post subject: Re: BigDecimalType is not handled in IdentifierGeneratorFact
PostPosted: Wed Jan 03, 2007 9:18 pm 
Newbie

Joined: Wed Jan 03, 2007 8:10 pm
Posts: 4
fischman_98 wrote:
Please see here...http://opensource.atlassian.com/projects/hibernate/secure/IssueNavigator.jspa

BigDecimalType is not handled in IdentifierGeneratorFactory - this problem has been rejected.

I disagree with the resolution. BIGINTEGER in all the documentation is the recommended map for Oracle NUMBER. So it seems to me that when a sequence returns a number, it should be automatically converted to a BigInteger in IdentifierGeneratorFactory.

Seems to me that it should be a standard return type. Is there any way to re-review this?


Yeah I agree. What's the point of supporting sequences when it doesn't work for Oracle using big_integer as recommended? Surely the number of Oracle installations out there warrants the change.

Anyway, a quick work-around would be to alter the HBM file and changing the primary key type from "big_decimal" to "long". The pojo would need to change as well.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 04, 2007 12:08 pm 
Beginner
Beginner

Joined: Thu May 18, 2006 2:58 pm
Posts: 25
Here's what I did..Hope it helps!

Code:
//$Id: OracleSequenceGenerator.java,v 1.15 2006/08/31 18:26:27 oneovthafew Exp $
package org.hibernate.com.portal.customtypes;

import java.io.Serializable;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.Properties;
import java.math.BigInteger;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.exception.JDBCExceptionHelper;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.mapping.Table;
import org.hibernate.type.Type;
import org.hibernate.util.PropertiesHelper;
import org.hibernate.id.PersistentIdentifierGenerator;
import org.hibernate.id.Configurable;
import org.hibernate.id.IdentifierGenerationException;

public class OracleSequenceGenerator implements PersistentIdentifierGenerator, Configurable {

   /**
    * The sequence parameter
    */
   public static final String SEQUENCE = "sequence";

   /**
    * The parameters parameter, appended to the create sequence DDL. For
    * example (Oracle):
    * <tt>INCREMENT BY 1 START WITH 1 MAXVALUE 100 NOCACHE</tt>.
    */
   public static final String PARAMETERS = "parameters";

   private String sequenceName;
   private String parameters;
   private Type identifierType;
   private String sql;

   private static final Log log = LogFactory.getLog(OracleSequenceGenerator.class);

   public void configure(Type type, Properties params, Dialect dialect) throws MappingException {
      this.sequenceName = PropertiesHelper.getString(SEQUENCE, params, "hibernate_sequence");
      this.parameters = params.getProperty(PARAMETERS);
      String schemaName = params.getProperty(SCHEMA);
        String catalogName = params.getProperty(CATALOG);

        if (sequenceName.indexOf(dialect.getSchemaSeparator() ) < 0) {
            sequenceName = Table.qualify( catalogName, schemaName, sequenceName, dialect.getSchemaSeparator() );
        }

        this.identifierType = type;
      sql = dialect.getSequenceNextValString(sequenceName);
   }

   public Serializable generate(SessionImplementor session, Object obj)
   throws HibernateException {
      try {

         PreparedStatement st = session.getBatcher().prepareSelectStatement(sql);
         try {
            ResultSet rs = st.executeQuery();
            try {
               rs.next();
               Serializable result = get(
                     rs, identifierType
                  );
               if ( log.isDebugEnabled() ) {
                  log.debug("Sequence identifier generated: " + result);
               }
               return result;
            }
            finally {
               rs.close();
            }
         }
         finally {
            session.getBatcher().closeStatement(st);
         }
         
      }
      catch (SQLException sqle) {
         throw JDBCExceptionHelper.convert(
                 session.getFactory().getSQLExceptionConverter(),
                 sqle,
                 "could not get next sequence value",
                 sql
            );
      }

   }
   
   public static Serializable get(ResultSet rs, Type type)
      throws SQLException, IdentifierGenerationException {
      
         Class clazz = type.getReturnedClass();
         if ( clazz==Long.class ) {
            return new Long( rs.getLong(1) );
         }
         else if ( clazz==Integer.class ) {
            return new Integer( rs.getInt(1) );
         }
         else if ( clazz==Short.class ) {
            return new Short( rs.getShort(1) );
         }
         else if ( clazz==String.class ) {
            return rs.getString(1);
         }
         else if ( clazz==BigInteger.class ) {
            return new BigInteger(rs.getString(1));
         }
         else {
            throw new IdentifierGenerationException("this id generator generates long, integer, short, BigInteger or string");
         }
         
      }

   public String[] sqlCreateStrings(Dialect dialect) throws HibernateException {
      String[] ddl = dialect.getCreateSequenceStrings(sequenceName);
      if ( parameters!=null ) ddl[ddl.length-1] += ' ' + parameters;
      return ddl;
   }

   public String[] sqlDropStrings(Dialect dialect) throws HibernateException {
      return dialect.getDropSequenceStrings(sequenceName);
   }

   public Object generatorKey() {
      return sequenceName;
   }

}


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 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.