[Hibernate] Problema em Inserção de objeto dependente

12 respostas
Cocota

Olá a todos, vim em busca de help.

Tô fora de casa, vou só introduzir o problema. Quando chegar eu boto os códigos de erro e os mapeamentos e tal.

O sistema controla projetos. Um projeto depende de um responsavel. (responsavel 1 : n projetos).

Eu tô inserindo um responsavel beleza.
Mas na hora de inserir um projeto, eu seleciono o responsavel, dou um setResponsavel e depois mando persistir o objeto projeto no banco. Me retorna um erro.

(org.hibernate…) .SQLGrammarException diz que acontece um erro por não conseguir fazer update em batch.

Alguma idéia inicial?

12 Respostas

_fs

Pode postar o stacktrace todo, a parte do código pertinente e os mapeamentos de ambas as classes?

Cocota

Vamo la,

Responsavel.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="demo">
<class name="br.rn.cefet.nudes.modelo.vo.Responsavel" table="responsavel" node="responsavel">
	
	<id name="id" type="int" column="id" unsaved-value="0">
	    <generator class="sequence">
	      <param name="sequence">idresponsavel</param>
        </generator>	      
	</id>
	<property name="nome" not-null="true" type="java.lang.String"/>
	<property name="cpf" not-null="true" type="java.lang.String"/>
	<property name="email" type="java.lang.String"/>
	<property name="senha" type="java.lang.String"/>
	<property name="fone" type="java.lang.String"/>
	
	<set name="projetos">
	  <key column="idresponsavel" />
	  <one-to-many class="br.rn.cefet.nudes.modelo.vo.Projeto" />
	</set>
</class>
</hibernate-mapping>

Projeto.hbm.xml

<?xml version="1.0"?>
<!DOCTYPE hibernate-mapping PUBLIC "-//Hibernate/Hibernate Mapping DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd">
<hibernate-mapping package="demo">
  <class name="br.rn.cefet.nudes.modelo.vo.Projeto" table="projeto" node="projeto">
	
	<id name="id" type="int" column="id" unsaved-value="0">
	    <generator class="sequence">
	      <param name="sequence">idprojeto</param>
        </generator>	      
	</id>
	
	<property name="titulo" not-null="true" type="java.lang.String"/>
	<property name="objetivoGeral" not-null="true" type="java.lang.String"/>
	<property name="objetivosEspecificos" not-null="true" type="java.lang.String"/>
	<property name="justificativa" not-null="true" type="java.lang.String"/>
	
	<many-to-one name="responsavel" 
			 class="br.rn.cefet.nudes.modelo.vo.Responsavel"
			 cascade="none"
     			 outer-join="true"
     			 update="true"
     			 insert="true"
     			 access="property"
     			 column="idresponsavel"/>
  </class>
</hibernate-mapping>

Erro 505
type Exception Report

exception

javax.servlet.ServletException: Could not execute JDBC batch update

org.apache.struts.action.RequestProcessor.processException(RequestProcessor.java:523)

org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:421)

org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:224)

org.apache.struts.action.ActionServlet.process(ActionServlet.java:1194)

org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:432)

javax.servlet.http.HttpServlet.service(HttpServlet.java:709)

javax.servlet.http.HttpServlet.service(HttpServlet.java:802)

org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:362)
root cause

org.hibernate.exception.SQLGrammarException: Could not execute JDBC batch update

org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:59)

org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)

org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:181)

org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:226)

org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:136)

org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:274)

org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)

org.hibernate.impl.SessionImpl.flush(SessionImpl.java:730)

org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:324)

org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:86)

/* Essas tres abaixo são classes minhas */

br.rn.cefet.nudes.modelo.percistencia.GenericDAO.executeOperacao(GenericDAO.java:59)

br.rn.cefet.nudes.modelo.negocio.Cadastrador.execute(Cadastrador.java:26)

br.rn.cefet.nudes.view.struts.action.CadastroProjetoAction.execute(CadastroProjetoAction.java:29)

org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:419)

org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:224)

org.apache.struts.action.ActionServlet.process(ActionServlet.java:1194)

org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:432)

javax.servlet.http.HttpServlet.service(HttpServlet.java:709)

javax.servlet.http.HttpServlet.service(HttpServlet.java:802)

org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:362)

Código da classe CadastroProjetoAction

imports...
public class CadastroProjetoAction extends Action{
	
	public ActionForward execute(ActionMapping actionMapping, ActionForm actionForm, HttpServletRequest req, HttpServletResponse res) throws Exception {
		
		ProjetoForm projetoForm = (ProjetoForm)actionForm;
                
                if (projetoForm.getOperacao() == OperacaoView.REMOVER){
                    projetoForm.getProjeto().setId(Integer.parseInt(req.getParameter("id")));
                }
                
		Cadastrador.getInstance().execute(projetoForm.getOperacao(), projetoForm.getProjeto()); //linha 29
		
		return actionMapping.findForward("sucesso");
	}      
}

Código Classe Cadastrador

imports...
public class Cadastrador extends AbstractNegocio implements Negocio {

	private static Cadastrador singleton;

	private Cadastrador() {

	}

	public synchronized static Cadastrador getInstance() {
		if (singleton == null)
			singleton = new Cadastrador();
		return singleton;
	}
                /*VOInterface é uma interface que é implementada pelas classes de modelo. Projeto e Responsavel.
                */
	public void execute(int operacao, VOInterface vo) throws DAOException {

		GenericDAO dao = getDAO();
		try {
                                                //linha 26
			dao.executeOperacao(operacao, vo);

		} catch (DAOException e) {
			System.out.println(e.getMessage());
		} finally {
			dao.close();
		}
	}

}

Código Classe GenericDAO

imports...
public class GenericDAO implements Persistencia {

	private Session session;

	public static final int INSERIR = 1;

	public static final int ATUALIZAR = 2;

	public static final int REMOVER = 3;

	public GenericDAO() {
		this.session = HibernateSessionFactory.currentSession();
	}

	public void executeOperacao(int operacao, VOInterface vo)
			throws DAOException {

	   Transaction tr = this.session.beginTransaction();

		switch (operacao) {
		case INSERIR:
			this.insert(vo);
			break;
		case ATUALIZAR:
			this.update(vo);
			break;
		case REMOVER:
			this.delete(vo);
			break;
		}

		//linha 59
                tr.commit();

	}
...continua classe

Meu problema é não ter nem noção do que significa esse erro.
Nem noção.

Cocota

Lendo outros topicos do Fórum do GUJ. Eu achei um que dava uma dica para setar a propriedade no hibernate.cfg.xml

<property name="hibernate.jdbc.batch_size">0</property>

Já fiz isso, o erro mudou, e eu não entendi nada novamente.

exception

javax.servlet.ServletException: could not insert: [br.rn.cefet.nudes.modelo.vo.Projeto]

org.apache.struts.action.RequestProcessor.processException(RequestProcessor.java:523)

org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:421)

org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:224)

org.apache.struts.action.ActionServlet.process(ActionServlet.java:1194)

org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:432)

javax.servlet.http.HttpServlet.service(HttpServlet.java:709)

javax.servlet.http.HttpServlet.service(HttpServlet.java:802)

org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:362)

root cause

org.hibernate.exception.SQLGrammarException: could not insert: [br.rn.cefet.nudes.modelo.vo.Projeto]

org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:59)

org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:43)

org.hibernate.persister.entity.BasicEntityPersister.insert(BasicEntityPersister.java:1869)

org.hibernate.persister.entity.BasicEntityPersister.insert(BasicEntityPersister.java:2200)

org.hibernate.action.EntityInsertAction.execute(EntityInsertAction.java:46)

org.hibernate.engine.ActionQueue.execute(ActionQueue.java:239)

org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:223)

org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:136)

org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:274)

org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:27)

org.hibernate.impl.SessionImpl.flush(SessionImpl.java:730)

org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:324)

org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:86)

br.rn.cefet.nudes.modelo.percistencia.GenericDAO.executeOperacao(GenericDAO.java:60)

br.rn.cefet.nudes.modelo.negocio.Cadastrador.execute(Cadastrador.java:26)

br.rn.cefet.nudes.view.struts.action.CadastroProjetoAction.execute(CadastroProjetoAction.java:29)

org.apache.struts.action.RequestProcessor.processActionPerform(RequestProcessor.java:419)

org.apache.struts.action.RequestProcessor.process(RequestProcessor.java:224)

org.apache.struts.action.ActionServlet.process(ActionServlet.java:1194)

org.apache.struts.action.ActionServlet.doPost(ActionServlet.java:432)

javax.servlet.http.HttpServlet.service(HttpServlet.java:709)

javax.servlet.http.HttpServlet.service(HttpServlet.java:802)

org.netbeans.modules.web.monitor.server.MonitorFilter.doFilter(MonitorFilter.java:362)

Também já mudei o método .save() para .saveOrUpdate() também não consigo persistir o objeto. O erro é igual ao primeiro listado aqui.

T

verifique se o Dialect setado eh o correto para o seu banco…

Cocota

takeshi,
Meu banco é o PostgreSQL 8.1
Esse é o dialeto escolhido e configurado no cfg.xml

<property name="dialect">
   org.hibernate.dialect.PostgreSQLDialect
</property>

Eu não acho que seja esse erro porque eu consigo inserir o objeto Responsavel.

_fs

Você está fazendo corretamente ao setar o responsável antes de salvar o projeto.

O código e o mapeamento parecem corretos, o que falta agora é o SQL gerado pelo Hibernate. O erro mostrado poderia ser melhor, mas o que foi mostrado é suficiente para deduzir que o problema ocorre na fase final: a excecução da query.

Então se o SQL não está sendo mostrado no console, adicione essa linha em seu log4j.properties:

log4j.logger.org.hibernate.SQL=DEBUG

Cocota

LIPE,

Vamo continuar que o papo tá bom.
O ShowSQL tá TRUE. Não tem erro nele.

Na sexta-feira de 17:30 eu troquei de SGBD. Botei o MySQL e junto com ele troquei o hibernate.cfg.xml por um que eu tinha pronto aqui. De primeira funcionou!
De cara eu culpei o hibernate-configuration que eu tava usando.
Vou colocar os dois aqui pra discutir em cima:
Antigo

<hibernate-configuration>

<session-factory>
	

                <property name="dialect">
                    org.hibernate.dialect.PostgreSQLDialect
                </property>
	<property name="connection.url">
                      jdbc:postgresql://localhost:5432/sispro
                </property>
	<property name="connection.username">postgres</property>
	<property name="connection.password">postgres</property>
	<property name="connection.driver_class">org.postgresql.Driver</property>
	<property name="transaction.factory_class">org.hibernate.transaction.JDBCTransactionFactory</property>
	<property name="connection.pool_size">10</property>
	<property name="statement_cache.size">10</property>
	<property name="connection.pool_size">10</property>
	<property name="connection.pool_size">10</property>
	<property name="show_sql">true</property>
	<property name="use_outer_join">false</property>
	<property name="max_fetch_depth">3</property>
        
	<mapping resource="config/hbm/Responsavel.hbm.xml" />
	<mapping resource="config/hbm/Projeto.hbm.xml" />

</session-factory>

</hibernate-configuration>

Atual

<hibernate-configuration>

<session-factory>
	
	
	<property name="hibernate.dialect">
            org.hibernate.dialect.MySQLDialect
	</property>
	<property name="hibernate.connection.driver_class">
            com.mysql.jdbc.Driver
	</property>
	<property name="hibernate.connection.url">
            jdbc:mysql://localhost/sispro?autoReconnect=true
	</property>
	<property name="hibernate.connection.username">
            root
	</property>
	<property name="hibernate.connection.password">
            root
	</property>		
		
		<!-- Condiguração do c3p0 -->
		
	<property name="hibernate.c3p0.max_size">10</property>
	<property name="hibernate.c3p0.min_size">2</property>
	<property name="hibernate.c3p0.timeout">5000</property>
	<property name="hibernate.c3p0.max_statements">10</property>
	<property name="hibernate.c3p0.idle_test_period">3000</property>
	<property name="hibernate.c3p0.acquire_increment">2</property>			

		<!-- Configurações de debug -->

        <property name="show_sql">true</property>
        <property name="use_outer_join">true</property>	
        <property name="hibernate.generate_statistics">true</property>
        <property name="hibernate.use_sql_comments">true</property>

        
	<mapping resource="config/hbm/Responsavel.hbm.xml" />
	<mapping resource="config/hbm/Projeto.hbm.xml" />

</session-factory>

</hibernate-configuration>
_fs

Não importa se o show_sql é true ou false. Se você configura o logger para imprimir apenas WARN e não DEBUG, o sql não é mostrado.

Se ao mudar de banco funcionou então há algum problema no PostgreSQLDialect que seria encontrado ao olharmos o sql gerado :smiley:

Cocota

Saquei Saquei…

foi mal… jurava ter visto ShowSQL=FALSE no seu post.

e os arquivos cfg.xml nao tem nada a ver?

_fs

Se só de trocar o banco e dialect resolveu, a priori tem nada a ver.

É bem improvável que seja um bug no Hibernate. É bem provável que você tenha cometido algum erro ao montar o banco de dados no MySQL. Alguma coluna com nome diferente ou qualquer coisa assim. Se pegar a query gerada e executá-la diretamente no banco de dados fica fácil pegar o erro.

rafaelglauber

Estou utilizando hibernate com annotations, tive que realizar a seguinte mudança para funcionar corretamente com postgresql: Na anotação @Column eu coloquei o nome da coluna entre ``, exemplo:@Column(name="password"). A partir dessa mudança tudo funcionou corretamente, inclusive no próprio nome da entidade fiz o mesmo procedimento na anotação correspondente. Creio que o principio do problema seja o mesmo, logo que faça o mesmo em seu arquivo de mapeamento acredito que irá funcionar.

B

Como vc esta fazendo para gerar a chave primária do Postgre? Creio que o seu problema esta ai, veja como a anotation @TableGenerator funciona que eu acho que vc vai resolver o seu problema com o Postgre.

Criado 7 de abril de 2006
Ultima resposta 28 de out. de 2008
Respostas 12
Participantes 5