JPA Transação múltiplos PERSIST

13 respostas
jpahibernate
B

Boa tarde,

Tenho alguns métodos que persistem objetos diferentes ao mesmo tempo e também atualiza registros em entidades diferentes, o problema está no Rollback, dependendo de onde ocorrer o erro a transação comita algumas informções.

Ex

em = Connection.emf.createEntityManager();

em.getTransaction().begin();

em.persist(venda);

em.persist(financeiro);

em.createQuery("UPDATE Estoque s SET s.qtd = s.qtd -1).executeUpdate();

em.getTransaction().commit();

Caso ocorro um erro apenas nos objetos financeiro, o update do estoque e a as vendas sao inseridas na base de dados.
O que posso fazer para evitar que isso aconteça?

13 Respostas

J
EntityManager em = createEntityManager();
em.getTransaction().begin();
try {
    // ...
    // ...
    em.getTransaction().commit();
} catch(Exception e) {
    em.getTransaction().rollback();
    throw e;
}
B

Já faço isso justamente por isso minha dúvida de o pq nao funcionar o rollback, ja que trato dentro de uma mesma transação e de um bloco try catch.

J

O que você postou não faz isso. Posta o código correto então, pois não dá pra advinhar.

B
try 
	{
		

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

		Date dataServer = (Date) em.createNativeQuery(
				ConnectionHib.SGBD.toLowerCase().equals("mysql") ? "SELECT NOW()" : "SELECT  SYSDATE FROM DUAL")
				.getSingleResult();

		
		
		recibo.setCodUsuario(codUsuario);
		recibo.setDocsQuitados("");			
		recibo.setNoQuitacao(new Integer(0));
		
		
		em.createQuery("UPDATE Numeracao s SET s.fcNoRecibo = s.fcNoRecibo+1 WHERE s.emp= :emp ")
		.setParameter("emp", emp.getCodigo())
		.executeUpdate();
		
		Integer noRecibo = seqDAO.getLastInsertCodigo(emp.getCodigo(), "fcNoRecibo");				
		recibo.setNoRecibo(noRecibo);		
		
		em.persist(recibo);

		em.getTransaction().commit();

	} 
	catch (Exception e) 
	{
		e.printStackTrace();
		em.getTransaction().rollback();

		throw e;
	} 
	finally 
	{
		em.close();
	}

Este é um exemplo, nesse caso persisto apenas uma entidade, mas dou um update em uma entidade que controla a numeracao dos recibos, caso de algum erro no persist do recibo, a numeracao ainda assim é afetada pelo update.

J

Afetado no banco de dados mesmo com rollback? Você debugando ele entrou no rollback?

B

Sim mesmo com o rollback ele afeta na base de dados, poderia ter algo a ver com a versão do mysql que estou usando a 5.1, o autocommit do hibernate está false, ele entra no rollback e da uma exception rollbackexception.

J

Então não deu rollback. Posta a mensagem de erro completa. Primeira vez que vejo dar erro em rollback.

B
jan 16, 2018 11:06:12 AM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions

WARN: SQL Error: 1048, SQLState: 23000

jan 16, 2018 11:06:12 AM org.hibernate.engine.jdbc.spi.SqlExceptionHelper logExceptions

ERROR: Column COD_OPERACAO cannot be null

jan 16, 2018 11:06:12 AM org.hibernate.engine.jdbc.batch.internal.AbstractBatchImpl release

INFO: HHH000010: On release of batch it still contained JDBC statements

jan 16, 2018 11:06:12 AM org.hibernate.internal.ExceptionMapperStandardImpl mapManagedFlushFailure

ERROR: HHH000346: Error during managed flush [org.hibernate.exception.ConstraintViolationException: could not execute statement]

javax.persistence.RollbackException: Error while committing the transaction

at org.hibernate.internal.ExceptionConverterImpl.convertCommitException(ExceptionConverterImpl.java:75)

at org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:71)

Eu deixei um atributo que é obrigatorio no banco sem informacao para forcar o erro, o update foi aplicado, mesmo com esta excecao lançada.

J

Em algum momento está entrando no commit do Hibernate.

org.hibernate.engine.transaction.internal.TransactionImpl.commit(TransactionImpl.java:71)

B

Sim, debugando, ele entra no commit depois vai para o rollback(), a exceção é lançada na execução comit e não no persist.

J

Seu reporte sobre o problema ficou confuso. Se chamar commit ele commita o que der certo se o script SQL já tiver ido pro banco. Veja se faltou executar Flush logo após cada persist. E se não me engano, tem como configurar auto flush.

B

Eu não executo flush após cada persist, mas fiz para testar e o mesmo erro persiste, uma parte da instrução sql ainda é gravado no banco.

J

Esse problema vai acontecer enquanto tiver algo pendente na sessão do hibernate para enviar ao banco. Hibernate é uma bomba mesmo, vai se acostumado.

Criado 15 de janeiro de 2018
Ultima resposta 16 de jan. de 2018
Respostas 13
Participantes 2