Solucionado (ver solução)
Solucionado
(ver solução)
16
respostas

Dúvida auto update schema

Olá pessoal eu estava realizando o exercício opcional do primeiro capitulo do curso de JPA e no exercício era para o meu banco contas ter sido atualizado o schema dele após a execução do meu código, adicionando o campo saldo assim como adicionado na entidade no java. Porém, não foi atualizado e tive que fazer um alter table na mão lá no banco. Eu peguei o projeto original que baixei no link disponibilizado, esqueci de algo?

Só para constar, estou usando o postegres.

16 respostas

Olá você lembrou de descomentar essa linhas ?

 EntityManagerFactory emf = Persistence
        .createEntityManagerFactory("contas-postgres");

e comentar essas linhas?

EntityManagerFactory emf = Persistence
                .createEntityManagerFactory("contas-mysql");

Sim, ele esta criando o entity manager com o persistence unit do postgres corretamente. Eu fiz um teste fazendo com que fosse criado a tabela pelo hibernate e ele cria, mas alterar (update table) no caso de adicionar um campo na tabela ele não faz.

Você poderia postar seu persistence.xml e sua classe conta?

    EntityManagerFactory emf = Persistence.createEntityManagerFactory("financas");

        EntityManager em = emf.createEntityManager();
        em.getTransaction().begin();

        em.persist(conta);

        em.getTransaction().commit();
        em.close();
    <persistence-unit name="contas-postgres">
        <provider>org.hibernate.ejb.HibernatePersistence</provider>
        <class>br.com.caelum.financas.modelo.Conta</class>
        <properties>
            <property name="javax.persistence.jdbc.driver" value="org.postgresql.Driver" />
            <property name="javax.persistence.jdbc.url" value="jdbc:postgresql://localhost/contas" />
            <property name="javax.persistence.jdbc.user" value="rafaelpbaptista" />
            <property name="javax.persistence.jdbc.password" value="" />

            <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" />
            <property name="hibernate.hbm2ddl.auto" value="update" />
            <property name="hibernate.show_sql" value="true" />
            <property name="hibernate.format_sql" value="true" />
        </properties>
    </persistence-unit>

Nesse trecho de código

  EntityManagerFactory emf = Persistence.createEntityManagerFactory("financas")

O que está entre aspas se refere a essa linha do XML

<persistence-unit name="contas-postgres">

Então o correto seria: 1ª Opção: mudar o Java

 EntityManagerFactory emf = Persistence.createEntityManagerFactory("contas-postgres")

2ª Opção: mudar o XML

<persistence-unit name="financas">

Note que se as propriedades diferem, como o seu código, quando executamos o programa ocorre uma execeção:

Exception in thread "main" javax.persistence.PersistenceException: No Persistence provider for EntityManager named financas

Espero ter ajudado, se está foi a solução não esqueça de marcar essa resposta como solução

ah não mandei errado o xml, no meu é como vc fala na segunda opção.

Ainda assim, não funciona.

O banco que você criou no postgres como se chama?

Banco contas

Você poderia mandar o que sai no terminal quando você executa o programa

Carlos, infelizmente agora não tenho acesso ao código, mas ele dá erro que a coluna "x" não existe na minha relação. Um erro do banco, driver postegres.

Quando tiver acesso, por favor poste pois me ajudara a identificar o erro

Carlos, finalmente tive um tempo para estudar.. ta corrida a vida e quando tem tempo da temporal na cidade... :/

bom, segue a pilha de erro.

Could not complete schema update
java.lang.NullPointerException
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125)
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:110)
    at org.hibernate.tool.hbm2ddl.DatabaseMetadata.getTableMetadata(DatabaseMetadata.java:129)
    at org.hibernate.cfg.Configuration.generateSchemaUpdateScript(Configuration.java:1133)
    at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:212)
    at org.hibernate.tool.hbm2ddl.SchemaUpdate.execute(SchemaUpdate.java:178)
    at org.hibernate.internal.SessionFactoryImpl.<init>(SessionFactoryImpl.java:503)
    at org.hibernate.cfg.Configuration.buildSessionFactory(Configuration.java:1750)
    at org.hibernate.ejb.EntityManagerFactoryImpl.<init>(EntityManagerFactoryImpl.java:94)
    at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:905)
    at org.hibernate.ejb.Ejb3Configuration.buildEntityManagerFactory(Ejb3Configuration.java:890)
    at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:57)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:63)
    at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:47)
    at br.com.caelum.financas.jpa.TesteJPA.main(TesteJPA.java:34)

Hibernate: 
    select
        nextval ('SEQ_CONTAS')
Hibernate: 
    insert 
    into
        Conta
        (agencia, banco, debitos, numero, saldo, titular, id) 
    values
        (?, ?, ?, ?, ?, ?, ?)
jul 14, 2016 8:44:07 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
WARN: SQL Error: 0, SQLState: 42703
jul 14, 2016 8:44:07 PM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions
ERROR: ERROR: column "debitos" of relation "conta" does not exist
  Posição: 36
Exception in thread "main" javax.persistence.RollbackException: Error while committing the transaction
    at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:92)
    at br.com.caelum.financas.jpa.TesteJPA.main(TesteJPA.java:47)
Caused by: javax.persistence.PersistenceException: org.hibernate.exception.SQLGrammarException: ERROR: column "debitos" of relation "conta" does not exist
  Posição: 36
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1377)
    at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1300)
    at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:80)
    ... 1 more
Caused by: org.hibernate.exception.SQLGrammarException: ERROR: column "debitos" of relation "conta" does not exist
  Posição: 36
    at org.hibernate.exception.internal.SQLStateConversionDelegate.convert(SQLStateConversionDelegate.java:122)
    at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49)
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:125)
    at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:110)
    at org.hibernate.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:129)
    at org.hibernate.engine.jdbc.internal.proxy.AbstractProxyHandler.invoke(AbstractProxyHandler.java:81)
    at com.sun.proxy.$Proxy8.executeUpdate(Unknown Source)
    at org.hibernate.engine.jdbc.batch.internal.NonBatchingBatch.addToBatch(NonBatchingBatch.java:56)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3028)
    at org.hibernate.persister.entity.AbstractEntityPersister.insert(AbstractEntityPersister.java:3469)
    at org.hibernate.action.internal.EntityInsertAction.execute(EntityInsertAction.java:88)
    at org.hibernate.engine.spi.ActionQueue.execute(ActionQueue.java:362)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:354)
    at org.hibernate.engine.spi.ActionQueue.executeActions(ActionQueue.java:275)
    at org.hibernate.event.internal.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:326)
    at org.hibernate.event.internal.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:52)
    at org.hibernate.internal.SessionImpl.flush(SessionImpl.java:1213)
    at org.hibernate.internal.SessionImpl.managedFlush(SessionImpl.java:402)
    at org.hibernate.engine.transaction.internal.jdbc.JdbcTransaction.beforeTransactionCommit(JdbcTransaction.java:101)
    at org.hibernate.engine.transaction.spi.AbstractTransactionImpl.commit(AbstractTransactionImpl.java:175)
    at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:75)
    ... 1 more
Caused by: org.postgresql.util.PSQLException: ERROR: column "debitos" of relation "conta" does not exist
  Posição: 36
    at org.postgresql.core.v3.QueryExecutorImpl.receiveErrorResponse(QueryExecutorImpl.java:2157)
    at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1886)
    at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:255)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.execute(AbstractJdbc2Statement.java:555)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.executeWithFlags(AbstractJdbc2Statement.java:417)
    at org.postgresql.jdbc2.AbstractJdbc2Statement.executeUpdate(AbstractJdbc2Statement.java:363)
    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.engine.jdbc.internal.proxy.AbstractStatementProxyHandler.continueInvocation(AbstractStatementProxyHandler.java:122)
    ... 17 more

Oi Mateus, parece que ta dando alguma coisa errada quando o hibernate vai atualizar os campos da sua tabela para adicionar a coluna debitos. Ele está reclamando justamente da falta desta coluna... Talvez no log tenha alguma informação, até pq falha de atualização de schema não gera erro no hibernate :(.

Outro jeito simples é vc adicionar a coluna diretamente na tabela :).

Alberto, é justamente o que estou fazendo, adicionando no banco via SQL. Porém queria saber o porquê não está funcionando o auto update do hibernate.

Oi Mateus, logo antes da exception tem uma mensagem assim no log: "Could not complete schema update"

Vê o que tem antes dela, desconfio que ali tenha algum indicativo do motivo da não atualização do schema.

solução!

Não utilize org.hibernate.dialect.PostgreSQLDialect. Segundo o javadoc do Hibernate este dialeto está deprecated. Utilizo org.hibernate.dialect.PostgreSQL82Dialect e não tenho mais problemas (é... já passei por esse mesmo problema por aqui).

Trecho do persistence.xml:

<property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQL82Dialect" />
<property name="hibernate.hbm2ddl.auto" value="update" />