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
) 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")
})