Mapeamento anormal de PK no Hibernate

Buenas pessoal, dei uma procurada na documentação do Hibernate(e também nas docs do Hibernate Annotations) e não achei nada relacionado ao mapeamento de geradores de PK anormais. Explicando: a classe que preciso mapear tem sua PK gerada através de uma procedure do banco(cadê aquele smile com ânsia de vômito?). Como eu poderia fazer esse mapeamento sem ter que fazer uma grande, gorda e feia gambiarra?

Notas: a procedure (que está num banco INGRES - a boa notícia é que o Hibernate vem com dialect bem atualizadinho pra ele já), que consulta uma tabela de parâmetros, onde cada linha possui um registro que contém o valor da pk. Então sim, a procedure consulta o valor, guarda numa variável, faz update pra n+1, e commita. altamente escalável.

Ouch! Que coisa mais incomum. Enfim, tente estas duas estratégias:
:arrow: tente usar @GeneratedValue(strategy=GenerationType.SEQUENCE …)
:arrow: ou então, tente usar as Hibernate Annotation Extensions, usando o “select” como gerador (aliás, tentaria esta última estratégia primeiro).

O que pode ser feito também é gerar um próprio Generator.

Sim, mas em último caso (no caso de desespero, por exemplo).

Ahhh!! Ignore a primeira estratégia! Tente usar o generator “assigned” (usando as Hibernate Annotations Extensions): http://www.hibernate.org/hib_docs/v3/reference/en/html_single/#mapping-declaration-id

Boa Daniel. Por sinal, é o mapeamento default,hehe.

** diego procura serra elétrica para brincar com ser que teve a brilhante idéia de criar uma procedure que atualiza uma sequence em uma tabela(!!) e devolve o valor.

Caramba :shock:

Quando agente acha que já viu de tudo, sempre tem coisa pior, pra quê o cara tá atualizando uma sequence no braço…

[quote=Maurício Linhares]Caramba :shock:

Quando agente acha que já viu de tudo, sempre tem coisa pior, pra quê o cara tá atualizando uma sequence no braço…[/quote]

Não duvide nunca da capacidade de uma ameba no cargo de programador :slight_smile:

Buenas, problema solucionado. Após pesquisar pelas alternativas (que não eram muitas, por sinal), chegamos em duas que seriam as mais “coerentes”:

  • Seguindo a linha de raciocínio que o Quirino sugeriu (de permitir que a aplicação controlasse a pk), seria um pouco (ok, seria uma enorme gambiarra feia e fedida), pois teriamos que criar um singleton da vida e fazer referência sempre. Maior trabalho pros desenvolvedores, resumindo, no way.

  • A segunda, que foi a adotada. Criamos (eu+Cuozzo+Lucas que agora trabalha comigo :slight_smile: ) um gerador próprio que implementa IdentifierGenerator. Não ficou a coisa mais linda do mundo, mas ficou decente. A implementação da classe ficou algo próximo disto:

[code]import java.io.Serializable;
import java.sql.CallableStatement;
import java.sql.SQLException;
import java.sql.Types;
import java.util.Properties;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.hibernate.EntityMode;
import org.hibernate.HibernateException;
import org.hibernate.MappingException;
import org.hibernate.dialect.Dialect;
import org.hibernate.engine.SessionImplementor;
import org.hibernate.exception.JDBCExceptionHelper;
import org.hibernate.id.Configurable;
import org.hibernate.id.IdentifierGenerator;
import org.hibernate.metadata.ClassMetadata;
import org.hibernate.type.Type;

public class PkGenerator implements Configurable, IdentifierGenerator {

   private String tableName;
   private String columnName;

   private static final String sql = "{?= call procedure_que_gera_a_pk(?, ?, ?)}";

   private static final Log log = LogFactory.getLog(PkGenerator.class);
   private static final String TABLE_NAME = "table";
   private static final String COLUMN_NAME = "column";

   public PkGenerator() {
   }

   public void configure(Type type, Properties params, Dialect dialect)
                   throws MappingException {

           tableName = params.getProperty(TABLE_NAME);
           columnName = params.getProperty(COLUMN_NAME);

   }

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

           ClassMetadata classMetadata =

session.getFactory().getClassMetadata(object.getClass());

           Serializable pkValue = generatePkValue(session);

           classMetadata.setIdentifier(object, pkValue, EntityMode.POJO);

           return pkValue;
   }

   private Serializable generatePkValue(SessionImplementor session) {

           Serializable pkValue = null;

           try {
                   CallableStatement cs = session.getBatcher().prepareCallableStatement(sql);

                   try {
                           cs.registerOutParameter(1, Types.INTEGER);
                           cs.setString(2, tableName);
                           cs.setString(3, columnName);
                           cs.setInt(4, 1);
                           cs.execute();

                           pkValue = new Integer(cs.getInt(1));

                           if ( log.isDebugEnabled() ) {
                                   log.debug("Sequence identifier generated: " + pkValue+" -

tableName: “+tableName+” columnName: "+columnName);
}
}catch(Exception e){
e.printStackTrace();
}
finally {
session.getBatcher().closeStatement(cs);
}

           } catch (SQLException sqle) {
                   sqle.printStackTrace();
                   throw JDBCExceptionHelper.convert(
                                   session.getFactory().getSQLExceptionConverter(),
                                   sqle,
                                   "could not get next sequence value",
                                   sql
                           );
           }

           return pkValue;
   }

}[/code]

E um exemplo de como ficou a utilização:

@Id @GeneratedValue(generator="pkGenerator") @GenericGenerator( name="pkGenerator", strategy="br.org.framework.model.pk.PkGenerator", parameters={ @Parameter(name="table", value="pessoa"), @Parameter(name="column", value="cd_pessoa") })

Não é por nada não, mas isso e bem comum dos lugares que eu venho…rsss… apesar de ser coisa do outro mundo e feio, nao sei pq tem gente que adora fazer isso… mas…

Opa… caros colegas.

Descupe, por acaso há um modo mais simples de se colocar um Auto Incremento na minha PK, pois quando realizado um cadastro não consigo gerar. Estou usando Hibernate + Annotations + JSF

Atenciosamente Valter