Erro ao executar o Merge do JPA

Estou tentando fazer um update em uma tabela usando o comando merge do JPA porém esta dando erro… estou chamando o merge aqui…

public boolean update(Programa prog) {
		em.getTransaction();
		em.getTransaction().begin();
		try {
			em.merge(prog);
			em.getTransaction().commit();
			return true;
			//em.find(arg0, arg1)
		}
		catch (Exception e){
			e.printStackTrace();
			em.getTransaction().rollback();
			return false;
		}
	}

e esse é o erro que esta ocorrendo

javax.persistence.RollbackException: Error while commiting the transaction
	at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:71)
	at br.com.is.ishistorico.dao.ProgramasDaoImpl.update(ProgramasDaoImpl.java:55)
	at br.com.is.ishistorico.gui.JPanelSEProgramas$4.actionPerformed(JPanelSEProgramas.java:273)
	at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
	at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
	at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
	at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
	at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
	at java.awt.Component.processMouseEvent(Unknown Source)
	at javax.swing.JComponent.processMouseEvent(Unknown Source)
	at java.awt.Component.processEvent(Unknown Source)
	at java.awt.Container.processEvent(Unknown Source)
	at java.awt.Component.dispatchEventImpl(Unknown Source)
	at java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.awt.Component.dispatchEvent(Unknown Source)
	at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
	at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
	at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
	at java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.awt.Window.dispatchEventImpl(Unknown Source)
	at java.awt.Component.dispatchEvent(Unknown Source)
	at java.awt.EventQueue.dispatchEvent(Unknown Source)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.run(Unknown Source)
Caused by: org.hibernate.exception.SQLGrammarException: Could not execute JDBC batch update
	at org.hibernate.exception.SQLStateConverter.convert(SQLStateConverter.java:90)
	at org.hibernate.exception.JDBCExceptionHelper.convert(JDBCExceptionHelper.java:66)
	at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:275)
	at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:266)
	at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:169)
	at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321)
	at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
	at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1028)
	at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:366)
	at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:137)
	at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:54)
	... 27 more
Caused by: java.sql.BatchUpdateException: Entrada em lote 0 delete from Programa_ProgramaHistorico where Programa_progId=24 foi abortada. Chame getNextException para ver a causa.
	at org.postgresql.jdbc2.AbstractJdbc2Statement$BatchResultHandler.handleError(AbstractJdbc2Statement.java:2537)
	at org.postgresql.core.v3.QueryExecutorImpl.processResults(QueryExecutorImpl.java:1328)
	at org.postgresql.core.v3.QueryExecutorImpl.execute(QueryExecutorImpl.java:351)
	at org.postgresql.jdbc2.AbstractJdbc2Statement.executeBatch(AbstractJdbc2Statement.java:2674)
	at org.hibernate.jdbc.BatchingBatcher.doExecuteBatch(BatchingBatcher.java:70)
	at org.hibernate.jdbc.AbstractBatcher.executeBatch(AbstractBatcher.java:268)
	... 35 more
java.lang.IllegalStateException: Transaction not active
	at org.hibernate.ejb.TransactionImpl.rollback(TransactionImpl.java:82)
	at br.com.is.ishistorico.dao.ProgramasDaoImpl.update(ProgramasDaoImpl.java:61)
	at br.com.is.ishistorico.gui.JPanelSEProgramas$4.actionPerformed(JPanelSEProgramas.java:273)
	at javax.swing.AbstractButton.fireActionPerformed(Unknown Source)
	at javax.swing.AbstractButton$Handler.actionPerformed(Unknown Source)
	at javax.swing.DefaultButtonModel.fireActionPerformed(Unknown Source)
	at javax.swing.DefaultButtonModel.setPressed(Unknown Source)
	at javax.swing.plaf.basic.BasicButtonListener.mouseReleased(Unknown Source)
	at java.awt.Component.processMouseEvent(Unknown Source)
	at javax.swing.JComponent.processMouseEvent(Unknown Source)
	at java.awt.Component.processEvent(Unknown Source)
	at java.awt.Container.processEvent(Unknown Source)
	at java.awt.Component.dispatchEventImpl(Unknown Source)
	at java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.awt.Component.dispatchEvent(Unknown Source)
	at java.awt.LightweightDispatcher.retargetMouseEvent(Unknown Source)
	at java.awt.LightweightDispatcher.processMouseEvent(Unknown Source)
	at java.awt.LightweightDispatcher.dispatchEvent(Unknown Source)
	at java.awt.Container.dispatchEventImpl(Unknown Source)
	at java.awt.Window.dispatchEventImpl(Unknown Source)
	at java.awt.Component.dispatchEvent(Unknown Source)
	at java.awt.EventQueue.dispatchEvent(Unknown Source)
	at java.awt.EventDispatchThread.pumpOneEventForFilters(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForFilter(Unknown Source)
	at java.awt.EventDispatchThread.pumpEventsForHierarchy(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.pumpEvents(Unknown Source)
	at java.awt.EventDispatchThread.run(Unknown Source)

se alguém pouder me ajudar…

no seu persistence.xml a propriedade auto commit está como false?

o persistence.xml não possui essa property

<?xml version="1.0" encoding="UTF-8"?> <persistence version="1.0" xmlns="http://java.sun.com/xml/ns/persistence" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"> <persistence-unit name="pu1"> <provider>org.hibernate.ejb.HibernatePersistence</provider> <class>br.com.is.ishistorico.model.Programa</class> <class>br.com.is.ishistorico.model.ProgramaHistorico</class> <properties> <property name="hibernate.connection.driver_class" value="org.postgresql.Driver"/> <property name="hibernate.connection.username" value="postgres"/> <property name="hibernate.connection.password" value="********"/> <property name="hibernate.connection.url" value="jdbc:postgresql://localhost:5432/ISHistorico"/> <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect"/> <property name="hibernate.show_sql" value="true"/> </properties> </persistence-unit> </persistence>

arrumei aqui o auto commit e deu o mesmo erro…tanto como “false” como “true”

Em relação ao seu código vc poderia dar esta melhorada:

public void update(Program prog) {

   try {
	   EntityTransaction entityTransaction = entityManager.getTransaction();
	   entityTransaction.begin();
	   entityManager.merge(prog);
	   entityTransaction.commit();
    } catch (PersistenceException e) {
         throw new PersistenceException(e);
    }
 }

Em relação ao erro, seu EntityManager está sendo criado a partir de um EntityManagerFactory ou está sendo injetado ?
Poste essa classe para o pessoal poder te ajudar melhor…

simmm…é um EntityManagerFactory

public class ProgramasDaoImpl<T> extends DAOImplHb     {

	
	private static EntityManagerFactory emf;
	private EntityManager em;
	
	public ProgramasDaoImpl(){
		emf = Persistence.createEntityManagerFactory("pu1");
		em = emf.createEntityManager();
		
	}
	
	public boolean create(Programa prog) {
		em.getTransaction().begin();
		try {
			em.persist(prog);
			em.getTransaction().commit();
			return true;
			//em.find(arg0, arg1)
		}
		catch (Exception e){
			e.printStackTrace();
			em.getTransaction().rollback();
			return false;
		}
	}
	
	public boolean update(Programa prog) {
		em.getTransaction();
		em.getTransaction().begin();
		try {
			em.merge(prog);
			em.getTransaction().commit();
			return true;
			//em.find(arg0, arg1)
		}
		catch (Exception e){
			e.printStackTrace();
			em.getTransaction().rollback();
			return false;
		}
	}
	
	public static ArrayList<Programa> listarProgramas() {
		ArrayList<Programa> lista = new ArrayList<Programa>();
		ProgramasDaoImpl dao = new ProgramasDaoImpl();
			lista = dao.loadAllPrograma();
		
		return lista;
	}
	
	
	public ArrayList<Programa> loadAllPrograma() throws InfrastructureException {
		ArrayList<Programa> c = new ArrayList<Programa>();  
		try {
			em.getTransaction();
			Query q = em.createQuery("SELECT progId, nomePrograma, modulo, descricao  FROM Programa" );
			ArrayList<Object[]> resultado =  (ArrayList<Object[]>) q.getResultList(); 
			Programa programa = null;
			
			 for (Object[] objects : resultado) {  
	               
	             programa = new Programa();  
	               
	             programa.setProgId((Integer)objects[0]);  
	             programa.setNomePrograma((String)objects[1]);  
	             programa.setModulo((Integer)objects[2]); 
	             programa.setDescricao((String)objects[3]);
	           
	           
	             c.add(programa);  
	               
	         }
			
			System.out.println(c); 
			
			return c; }
		catch (Exception e){
			e.printStackTrace();
			em.getTransaction().rollback();
			return null;}
	}
	
	public ArrayList<Programa> loadProgramaByProgId(int progId) throws InfrastructureException {
		ArrayList<Programa> c = new ArrayList<Programa>();  
		try {
			em.getTransaction();
			Query q = em.createQuery("SELECT progId, nomePrograma, modulo, descricao  FROM Programa where progId = "+progId );
			ArrayList<Object[]> resultado =  (ArrayList<Object[]>) q.getResultList(); 
			Programa programa = null;
			
			 for (Object[] objects : resultado) {  
	               
	             programa = new Programa();  
	               
	             programa.setProgId((Integer)objects[0]);  
	             programa.setNomePrograma((String)objects[1]);  
	             programa.setModulo((Integer)objects[2]); 
	             programa.setDescricao((String)objects[3]);
	           
	           
	             c.add(programa);  
	               
	         }
			
			System.out.println(c); 
			
			return c; }
		catch (Exception e){
			e.printStackTrace();
			em.getTransaction().rollback();
			return null;}
	}
}
	

Humm… Já que é criado por um EnityManagerFactory faça um teste de trocar o tipo de transação no persistence.xml, para ver se continua o mesmo erro…

 <persistence-unit name="pu1" transaction-type="RESOURCE_LOCAL">  
  
 </persistence-unit>

sim…continua o mesmo erro

=/

O persist do entity manager dá o mesmo problema ou so ocorrre com o merge ?

só no Merge…o Persist funcionou de boa…

Meio estranho porque a froma com que os dois estão implementados está muito parecida…

1 - Tem apenas uma diferença no seu merge, retire aquele em.getTransaction(); da linha 29 , meio redundante (se possível otimize o método da forma que eu postei no primeiro post)…

2 - Se mesmo assim não funcionar debuge os dois métodos para ver se no merge existe algum comportamento diferente do persist, verifique principalmente o getTransaction()

eu retirei o em.getTransaction(); e fiz o debug…os dois se comportram da mesma maneira…porém o merge continua com o mesmo erro…

Então se no mesmo método que você faz o merge vc mudar para persist ele funciona?

sim…

hehehhe

hahahahahhaha… Fala sério…

sera que pode ter algo a ver com o mapeamento nas classes? as relações e td mais?

mais dai não estaria inserindo com o persist tb né…

É estranho pq ambos merge e persist exigem que exista uma transação aberta para fazer a ação de persistência…Tinha que dar o mesmo erro no persist tbm…

Outra coisa se fosse um erro específico do merge(pela exceção que vc postou não é o caso) a exceção seria outra, seria mais específica…

Não sei se vc pode fazer isso mas eu mudaria seu projeto para ter as transações gerenciadas pelo container, além de ficar com o código mais limpo (sem ter que ficar abrido e comitando transações) vc não tem estes tipos de dores de cabeça que vc está tendo…

pois é o projeto eu não posso mudar por ser um padrão da empresa…

a solução é continuar tentando mesmo

Quando vc utiliza o merge ele da erro em ambas as situações ? Quando tenta gravar uma entidade do zero ou quando tenta atualizar uma já existente ?

Em certos casos é interessante rever os padrões para ter aplicações mais flexíveis e mais fáceis de se dar manutenção…E ter transações gerenciadas no braço pode gerar estes problemas que vc está tendo e muitos outros…