2012-09-20 23 views
12

Casi lo dice en el título. Tengo una clase que se ve algo como esto:Cómo asignar una cadena a una secuencia de base de datos en Hibernate

@Entity 
@Table(name="FOO") 
public class Foo { 

    private String theId; 

    @Id 
    @Column(name = "FOO_ID") 
    @GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "fooIdSeq") 
    @SequenceGenerator(name = "fooIdSeq", sequenceName = "SQ_FOO_ID", allocationSize = 10) 
    public String getTheId() { return theId; } 

    public String setTheId(String theId) { this.theId = theId; } 
} 

El uso de Oracle 11g, la columna de la FOO_ID es una VARCHAR2, pero la secuencia SQ_FOO_ID produce una NUMBER. La base de datos aparentemente está contento con esto, pero la aplicación necesita poder admitir identificadores no numéricos que pueden haberse insertado en esta columna fuera de la aplicación.

Considerando el código anterior, obtengo un org.hibernate.id.IdentifierGenerationException: Unknown integral data type for ids : java.lang.String. ¿Hay alguna manera de hacer este mapeo?

Uso de Hibernate 3.6.

Respuesta

10

Implemente una clase IdentifierGenerator personalizada; desde un blog post:

import java.io.Serializable; 
import java.sql.Connection; 
import java.sql.PreparedStatement; 
import java.sql.ResultSet; 
import java.sql.SQLException; 

import org.hibernate.HibernateException; 
import org.hibernate.engine.spi.SessionImplementor; 
import org.hibernate.id.IdentifierGenerator; 

public class StringKeyGenerator implements IdentifierGenerator { 

    @Override 
    public Serializable generate(SessionImplementor session, Object collection) throws HibernateException { 
     Connection connection = session.connection(); 
     PreparedStatement ps = null; 
     String result = ""; 

     try { 
      // Oracle-specific code to query a sequence 
      ps = connection.prepareStatement("SELECT TABLE_SEQ.nextval AS TABLE_PK FROM dual"); 
      ResultSet rs = ps.executeQuery(); 

      if (rs.next()) { 
       int pk = rs.getInt("TABLE_PK"); 

       // Convert to a String 
       result = Integer.toString(pk); 
      } 
     } catch (SQLException e) { 
      throw new HibernateException("Unable to generate Primary Key"); 
     } finally { 
      if (ps != null) { 
       try { 
        ps.close(); 
       } catch (SQLException e) { 
        throw new HibernateException("Unable to close prepared statement."); 
       } 
      } 
     } 

     return result; 
    } 
} 

Anotar la entidad PK así:

@Id 
@GenericGenerator(name="seq_id", strategy="my.package.StringKeyGenerator") 
@GeneratedValue(generator="seq_id") 
@Column(name = "TABLE_PK", unique = true, nullable = false, length = 20) 
public String getId() { 
    return this.id; 
} 

Debido a un error en Eclipse, un error podría ser elevado que el generador (seq_id) no está definido en la unidad de persistencia . Ponga esto en una advertencia de la siguiente manera:

  1. Seleccionar ventana »Preferencias
  2. Expandir persistencia de Java» APP »Errores/Advertencias
  3. Haga clic consultas y generadores
  4. establecer Generator es no definido en la unidad de persistencia a: Warning
  5. Haga clic en OK para aplicar los cambios y cerrar el diálogo
3

Este es otro enfoque:

parámetro
import java.io.Serializable; 

import org.hibernate.engine.spi.SessionImplementor; 
import org.hibernate.id.IdentifierGeneratorHelper.BigDecimalHolder; 
import org.hibernate.id.IntegralDataTypeHolder; 
import org.hibernate.id.SequenceGenerator; 

public class StringSequenceGenerator extends SequenceGenerator { 
    @Override 
    public Serializable generate(SessionImplementor session, Object obj) { 
     return super.generate(session, obj).toString(); 
    } 

    protected IntegralDataTypeHolder buildHolder() { 
     return new BigDecimalHolder(); 
    } 
} 

La secuencia tiene que ser especificado en la propiedad id como en el siguiente ejemplo:

@Id 
@GenericGenerator(name = "STRING_SEQUENCE_GENERATOR", strategy = "mypackage.StringSequenceGenerator", parameters = { @Parameter(name = "sequence", value = "MY_SEQUENCE_NAME") }) 
@GeneratedValue(strategy = GenerationType.SEQUENCE, generator = "STRING_SEQUENCE_GENERATOR") 
@Column(name = "MY_ID") 
public String getMyId() { 
    return this.myId; 
} 
Cuestiones relacionadas