Sequence default banco x Hibernate

252 views
Skip to first unread message

Jullierme Barros

unread,
Jun 16, 2007, 11:01:47 AM6/16/07
to PBJug
Bom dia Galera....

Estou com uma dúvida sobre como configurar o hibernate pra deixar o
banco de dados inserir um valor automaticamente (sequence) ao id.

Bom ele esta inserindo normalmente, está usando a seqüência do banco
de dados normalmente...

O problema é que ele esta dando um select nextval ('minha_sequencia')
antes de inserir. Não é preciso que o hibernate descubra inicialmente
o valor da seqüência, é só ele colocar um default no compo id do
insert que o próprio banco se encarregara de gerar a chave....


Tem como eu configurar o hibernate de forma que ele deixe o banco
inserir a chave ou isso é um comportamento padrão??

PS. Estou usando Annotations


Muito obrigado!!

Maurício Linhares

unread,
Jun 16, 2007, 11:08:16 AM6/16/07
to pb...@googlegroups.com
Acho que se você usar o GenerationType.IDENTITY ele deve fazer isso.

--
Mauricio Linhares - http://maujr.org/
Grupo de Usuários Java da Paraíba - http://pbjug.org/
João Pessoa, PB, (83) 3231-5419

fabricio epaminondas

unread,
Jun 16, 2007, 11:23:18 AM6/16/07
to pb...@googlegroups.com
Tem como configurar amigo! Tem uma dicas na refência lá no hibernate.org no tópico 2.2:

-  Vc pode deixar o controle de geração do ID automaticamente com o banco caso vc játenha configurado, no caso ele vai usar uma sequência, uma coluna auto_increment, ou seja lá o que vc configurou:
 
    @Id    @GeneratedValue(strategy=GenerationType.AUTO)
    @Column(name = "idFornecedor", unique = true, nullable = false, insertable = true, updatable = true)
    public int getIdFornecedor() {
        return this.idFornecedor;
    }

- Ou vc pode escolher especificamente que gerador usar:

- uma sequência
@Id @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="SEQ_STORE")
public Integer getId() { ... }

- um identificador
The next example uses the identity generator:
@Id @GeneratedValue(strategy=GenerationType.IDENTITY)

Entre outros que o hibernate oferece desde que seu BD suporte =)

 []'s

Em 16/06/07, Maurício Linhares <mauricio...@gmail.com> escreveu:

Jullierme Silva Barros

unread,
Jun 16, 2007, 11:51:55 AM6/16/07
to pb...@googlegroups.com
humm.... valeu pelas dicas....


vamos aos testes!

Obrigado!

Em 16/06/07, fabricio epaminondas < fabri...@gmail.com> escreveu:



--
==================================
                Jullierme Silva Barros                  
          Sistemas de Informação UEG            
                                                                  
              jullie...@gmail.com                
              julier...@hotmail.com            
==================================

Jullierme Silva Barros

unread,
Jun 16, 2007, 12:26:11 PM6/16/07
to pb...@googlegroups.com
Bom eu utilizei SEQUENCE e IDENTITY. Os dois funcionaram da mesma forma que estava antes (AUTO)

Dae eu achei uma configuração na documentação que possibilita o uso de PreparedStatment.getGeneratedKeys() em drivers JDBC3 para recuperar chaves geradas nativamente depois da inserção.
       
        <property name="hibernate.jdbc.use_get_generated_keys">true</property>

Meu banco eh postgresql 8.2 e atualizei o conector para versão JDBC 4, tentei também com a versão 3 e uma exceção eh gerada dizendo que o "Retorno de chaves geradas automaticamente não é suportado."

Será que existe uma forma de contornar isso??


Obrigado!!!!

Em 16/06/07, Jullierme Silva Barros < jullie...@gmail.com> escreveu:

fabricio epaminondas

unread,
Jun 16, 2007, 1:23:50 PM6/16/07
to pb...@googlegroups.com
Que camada não suporta o retorno das chaves geradas automaticamente, o  bd ou hibernate? diz onde ocorre essa exeção

Jullierme Silva Barros

unread,
Jun 16, 2007, 2:49:54 PM6/16/07
to pb...@googlegroups.com
Pelo que eu entendi, esse trabalho de retorno de chaves é feito pelo conector do banco de dados, que me parece que são conectores do tipo JDBC 3(Eh mais ou menos isso que diz a documentação).

Quando eu abilito a propriedade
 <property name="hibernate.jdbc.use_get_generated_keys">true</property> eh gerada esta exceção


" org.hibernate.exception.GenericJDBCException: could not insert:"


no log


WARN [http-8080-1] (JDBCExceptionReporter.java:77) - SQL Error: 0, SQLState: 0A000
ERROR [http-8080-1] (JDBCExceptionReporter.java :78) - Retorno de chaves geradas automaticamente não é suportado.
org.hibernate.exception.GenericJDBCException: could not insert: [T066_enquete]
at org.hibernate.exception.SQLStateConverter.handledNonSpecificException (SQLStateConverter.java:103)
    at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:91)
    at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)
    at org.hibernate.id.insert.AbstractReturningDelegate.performInsert (AbstractReturningDelegate.java:40)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:2158)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java :2631)
    at org.hibernate.action.EntityIdentityInsertAction.execute(EntityIdentityInsertAction.java:48)
    at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:250)
    at org.hibernate.event.def.AbstractSaveEventListener.performSaveOrReplicate (AbstractSaveEventListener.java:298)
    at org.hibernate.event.def.AbstractSaveEventListener.performSave(AbstractSaveEventListener.java:181)
    at org.hibernate.event.def.AbstractSaveEventListener.saveWithGeneratedId (AbstractSaveEventListener.java:107)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.saveWithGeneratedOrRequestedId(DefaultSaveOrUpdateEventListener.java:187)
    at org.hibernate.event.def.DefaultSaveEventListener.saveWithGeneratedOrRequestedId (DefaultSaveEventListener.java:33)
    at org.hibernate.event.def.DefaultSaveOrUpdateEventListener.entityIsTransient(DefaultSaveOrUpdateEventListener.java:172)
    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 :535)
    at org.hibernate.impl.SessionImpl.save(SessionImpl.java:523)
    at org.hibernate.impl.SessionImpl.save(SessionImpl.java:519)
    at T066_enqueteDAO.salvar(T066_enqueteDAO.java:24)
    at Teste.isSalvar (Teste.java:48)
    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.apache.el.parser.AstValue.invoke(AstValue.java:131)
    at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:276)
    at com.sun.faces.application.MethodBindingMethodExpressionAdapter.invoke (MethodBindingMethodExpressionAdapter.java:77)
    at javax.faces.component.UICommand.broadcast(UICommand.java:376)
    at org.ajax4jsf.framework.ajax.AjaxActionComponent.broadcast(AjaxActionComponent.java:47)
    at org.ajax4jsf.framework.ajax.AjaxViewRoot.processEvents(AjaxViewRoot.java:180)
    at org.ajax4jsf.framework.ajax.AjaxViewRoot.broadcastEvents(AjaxViewRoot.java:158)
    at org.ajax4jsf.framework.ajax.AjaxViewRoot.processApplication (AjaxViewRoot.java:329)
    at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:97)
    at com.sun.faces.lifecycle.LifecycleImpl.phase(LifecycleImpl.java:251)
    at com.sun.faces.lifecycle.LifecycleImpl.execute (LifecycleImpl.java:117)
    at javax.faces.webapp.FacesServlet.service(FacesServlet.java:244)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:290)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter (ApplicationFilterChain.java:206)
    at org.ajax4jsf.framework.ajax.xmlfilter.BaseXMLFilter.doXmlFilter(BaseXMLFilter.java:96)
    at org.ajax4jsf.framework.ajax.xmlfilter.BaseFilter.doFilter(BaseFilter.java:220)
    at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235)
    at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206)
    at org.apache.catalina.core.StandardWrapperValve.invoke (StandardWrapperValve.java:228)
    at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:175)
    at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:128)
    at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:104)
    at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109)
    at org.apache.catalina.connector.CoyoteAdapter.service (CoyoteAdapter.java:216)
    at org.apache.coyote.http11.Http11Processor.process(Http11Processor.java:844)
    at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:634)
    at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:445)
    at java.lang.Thread.run(Unknown Source)
Caused by: org.postgresql.util.PSQLException: Retorno de chaves geradas automaticamente não é suportado.
    at org.postgresql.jdbc3.AbstractJdbc3Connection.prepareStatement(AbstractJdbc3Connection.java:352)
    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 com.mchange.v2.c3p0.stmt.GooGooStatementCache$1StmtAcquireTask.run (GooGooStatementCache.java:525)
    at com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread.run(ThreadPoolAsynchronousRunner.java:547)


fabricio epaminondas

unread,
Jun 16, 2007, 3:02:13 PM6/16/07
to pb...@googlegroups.com
Envia tbm o código onde vc salva o objeto.

2007/6/16, Jullierme Silva Barros <jullie...@gmail.com>:

Jullierme Silva Barros

unread,
Jun 16, 2007, 4:01:02 PM6/16/07
to pb...@googlegroups.com
Bom eu populo meus POJOs

            String pergunta = "Pergunta enquete";
            String resp1 = "alternativa 1";
            String resp2 = "alternativa  2";
            String resp3 = "alternativa  3";
            String resp4 = "alternativa  4";
           
            T066_enquete t066 = new T066_enquete();
            t066.setT066_pergunta(pergunta);
            t066.setT066_condicao(1);

            T067_alternativas_enquete at1 = new T067_alternativas_enquete(resp1,0);
            T067_alternativas_enquete at2 = new T067_alternativas_enquete(resp2,0);
            T067_alternativas_enquete at3 = new T067_alternativas_enquete(resp3,0);
            T067_alternativas_enquete at4 = new T067_alternativas_enquete(resp4,0);
           
            t066.getAlternativas().add(at1);
            t066.getAlternativas().add(at2);
            t066.getAlternativas ().add(at3);
            t066.getAlternativas().add(at4);
           
         
//Agora eu persisto meu objeto enquete, que automaticamente persistirá suas alternativas

            new T066_enqueteDAO().salvar(t066);




O método salvar la so tem comando session.save(t066)


Eu estou apenas começando com o hibernate, e estou fazendo alguns testes. Ainda não criei nada complexo



O meu enquete esta:


@Entity
@org.hibernate.annotations.Entity(mutable = true, dynamicInsert = true, dynamicUpdate = true)
@Table(name = "t066_enquete")
@SequenceGenerator(name = "t066_enquete_t066_codigo_seq", sequenceName = "t066_enquete_t066_codigo_seq")

public class T066_enquete implements Serializable{

    Integer t066_codigo;
    String t066_pergunta;
    Date t066_data_hora;
    int t066_condicao;
    List <T067_alternativas_enquete> alternativas = new ArrayList<T067_alternativas_enquete>();
   
    public T066_enquete() {
    }

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY, generator = "t066_enquete_t066_codigo_seq")
    @Column(name = "t066_codigo")

    public Integer getT066_codigo() {
        return t066_codigo;
    }
    public void setT066_codigo(Integer t066_codigo) {
        this.t066_codigo = t066_codigo;
    }

    @Column(name = "t066_pergunta")
    public String getT066_pergunta() {
        return t066_pergunta;
    }
    public void setT066_pergunta(String t066_pergunta) {
        this.t066_pergunta = t066_pergunta;
    }

    @Temporal( TemporalType.TIMESTAMP)
    @Column(name = "t066_data_hora")
    public Date getT066_data_hora() {
        return t066_data_hora;
    }
    public void setT066_data_hora(Date t066_data_hora) {
        this.t066_data_hora = t066_data_hora;
    }
   
    @Column(name = "t066_condicao")
    public int getT066_condicao() {
        return t066_condicao;
    }
    public void setT066_condicao(int t066_condicao) {
        this.t066_condicao = t066_condicao;
    }
   
    @OneToMany(cascade = CascadeType.ALL)
    @JoinColumn(name="t066_codigo")
    public List<T067_alternativas_enquete> getAlternativas() {
        return alternativas;
    }
    public void setAlternativas(List<T067_alternativas_enquete> alternativas) {
        this.alternativas = alternativas;
    }
}


e as alternativas


@Entity
@org.hibernate.annotations.Entity(mutable = true, dynamicInsert = true, dynamicUpdate = true)
@Table(name = "t067_alternativas_enquete")
@SequenceGenerator(name = "t067_alternativas_enquete_t067_codigo_seq",
                   sequenceName = "t067_alternativas_enquete_t067_codigo_seq")

public class T067_alternativas_enquete {

    Integer t067_codigo;
    Integer t066_codigo;
    String t067_alternativa;
    Integer t067_contador;
    T066_enquete t066_enquete;
   
    public T067_alternativas_enquete() {
    }
   
    public T067_alternativas_enquete(String t067_alternativa,Integer t067_contador) {
        this.t067_alternativa = t067_alternativa;
        this.t067_contador = t067_contador;
    }
   
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO, generator = "t067_alternativas_enquete_t067_codigo_seq")
    @Column(name = "t067_codigo")
    public Integer getT067_codigo() {
        return t067_codigo;
    }
    public void setT067_codigo(Integer t067_codigo) {
        this.t067_codigo = t067_codigo;
    }
   
/*    @Column(name = "t066_codigo")
    public Integer getT066_codigo() {
        return t066_codigo;
    }
    public void setT066_codigo(Integer t066_codigo) {
        this.t066_codigo = t066_codigo;
    }
*/
    @Column(name = "t067_alternativa")
    public String getT067_alternativa() {
        return t067_alternativa;
    }
    public void setT067_alternativa(String t067_alternativa) {
        this.t067_alternativa = t067_alternativa;
    }
   
    @Column(name = "t067_contador")
    public Integer getT067_contador() {
        return t067_contador;
    }
    public void setT067_contador(Integer t067_contador) {
        this.t067_contador = t067_contador;
    }
   
    @ManyToOne
//    @JoinColumn(name="t066_codigo", insertable=false, updatable=false)
    @ForeignKey(name="t066_codigo")
    public T066_enquete getT066_enquete() {
        return t066_enquete;
    }
    public void setT066_enquete(T066_enquete t066_enquete) {
        this.t066_enquete = t066_enquete;
    }
   

Valeu pela ajuda!

Maurício Linhares

unread,
Jun 16, 2007, 6:16:15 PM6/16/07
to pb...@googlegroups.com
Não, não existe uma forma de contornar isso, se o seu driver não suporta, não tem como você utilizar.


On 6/16/07, Jullierme Silva Barros < jullie...@gmail.com> wrote:
Bom eu utilizei SEQUENCE e IDENTITY. Os dois funcionaram da mesma forma que estava antes (AUTO)

Dae eu achei uma configuração na documentação que possibilita o uso de PreparedStatment.getGeneratedKeys() em drivers JDBC3 para recuperar chaves geradas nativamente depois da inserção.
       
        <property name="hibernate.jdbc.use_get_generated_keys">true</property>

Meu banco eh postgresql 8.2 e atualizei o conector para versão JDBC 4, tentei também com a versão 3 e uma exceção eh gerada dizendo que o "Retorno de chaves geradas automaticamente não é suportado."

Será que existe uma forma de contornar isso??


Obrigado!!!!




fabricio epaminondas

unread,
Jun 16, 2007, 11:18:00 PM6/16/07
to pb...@googlegroups.com
Em alguns dialects do hibernate o suporte e esse recurso foi retirado, pode ser seu caso, agr quanto a deixar o controle da geração do ID com o banco a annotation GenerationType.AUTO resolve a parada sim, ela faz com que o hibernate não use nenhum gerador próprio mas sim insere os dados direto no BD sabendo que ele vai "se virar", tanto que se vc deixa AUTO e não configura no próprio BD nenhum sequence ou outro gerador dá erro.

Em 16/06/07, Maurício Linhares <mauricio...@gmail.com> escreveu:
Não, não existe uma forma de contornar isso, se o seu driver não suporta, não tem como você utilizar.

Jullierme Silva Barros

unread,
Jun 16, 2007, 11:49:06 PM6/16/07
to pb...@googlegroups.com
Isso eh verdade, o banco se encarrega de gerar a chave....

mas eu não entendo o seguinte, ele continua dando um select nextval('hibernate_sequence')


veja soh, aquele código que eu citei anteriormente, ele faz....



//acredito que ele faz estes 5 nextval, 1 para o id do pai e outros para os 4 filhos

Hibernate: select nextval ('hibernate_sequence')

Hibernate: select nextval ('hibernate_sequence')

Hibernate: select nextval ('hibernate_sequence')

Hibernate: select nextval ('hibernate_sequence')

Hibernate: select nextval ('hibernate_sequence')


//Insere a enquete

Hibernate: insert into t066_enquete (t066_condicao, t066_pergunta, t066_codigo) values (?, ?, ?)


//insere as alternativas da enquete

Hibernate: insert into t067_alternativas_enquete (t067_alternativa, t067_contador, t067_codigo) values (?, ?, ?)

Hibernate: insert into t067_alternativas_enquete (t067_alternativa, t067_contador, t067_codigo) values (?, ?, ?)

Hibernate: insert into t067_alternativas_enquete (t067_alternativa, t067_contador, t067_codigo) values (?, ?, ?)

Hibernate: insert into t067_alternativas_enquete (t067_alternativa, t067_contador, t067_codigo) values (?, ?, ?)

//agora ele atualiza as quatro chaves estrangeiras da tabela de alternativas com o id da enquete, ja que //inicialmente o hibernate os definiu como null. Ele ja persistiu a enquete, então não vejo necessidade de fazer //estes quatro updates

Hibernate: update t067_alternativas_enquete set t066_codigo=? where t067_codigo=?

Hibernate: update t067_alternativas_enquete set t066_codigo=? where t067_codigo=?

Hibernate: update t067_alternativas_enquete set t066_codigo=? where t067_codigo=?

Hibernate: update t067_alternativas_enquete set t066_codigo=? where t067_codigo=?


Karamba, este comportamento não me agrada.... tenho comigo que devo estar fazendo algo errado srsrssrs


Valeu pelas dicas!!!

Jullierme Silva Barros

unread,
Jun 18, 2007, 2:42:04 PM6/18/07
to pb...@googlegroups.com
Bom pelo que eu entendi, o hibernate pega o id dos registros antes de inserir no banco, pra atualizar os ids dos pojos....

Pelo que eu pude entender, não existe uma forma de deixar o banco cuidar do id sozinho. Ou vc diz ao hibernate qual seqüencia usar ou ele cria uma e utiliza ela onde não houver seqüencia definida.
Na minha opinião eh uma péssima idéia deixar o hibernate se virar com a geração da chave, porque de todo jeito ele irá pegar os ids antes de inserir.... se vc não fornece a seqüencia do banco então ele cria a seqüencia "hibernate_sequence" e utiliza ela pra todas as entidades. Assim ele não irá utilizar de forma alguma a sua seqüência definida na geração das tabelas. E o pior, como é apenas uma seqüencia pra todas as tabelas, se o último registro for, por exemplo da tabela "A" o número 13, e houver outras inserções em outras tabelas, por exemplo 15 inserções em outras tabelas, quando ele voltar a inserir na tabela "A" o próximo id será 28 e não 14.
Reply all
Reply to author
Forward
0 new messages