Transaction marked as rollbackOnly

1 resposta
E

Senhores,

considerando o modelo de classes em anexo, tenho uma página de inclusão do cliente. Lá o usuário tem a chance de "validar" um logradouro que ela escrever. Quando ele o faz, o banco de dados prepara o formulário preenchendo o endereço já existente se só existir um logradouro de acordo com o que foi procurado ou exibe uma lista caso contrário.

A questão é que, se o logradouro não está pré-cadastrado o usuário define o novo endereço na mesma página e as regras do negócio resolvem o problema. Mas se por acaso é digitado um bairro, logradouro ou cidade inexistente, estes também são inserido automaticamente.

Este é o código do JPA que trata a coisa:

@Transactional(readOnly=false)
    public void salvar(Cliente cliente){
    	RegiaoEndereco reCliente = cliente.getEndereco().getRegiaoEndereco();
    	TipoEndereco t = null;
   		t = bU.buscarTipoEndereco(reCliente.getTipoEndereco().getId()); 

   		Logradouro l = null;
   		try {
   			l = bU.buscarLogradouroExato(reCliente.getLogradouro().getNome());
   			em.merge(l);
   		} catch (NoResultException n){
   			l = new Logradouro();
   			l.setNome(reCliente.getLogradouro().getNome());
   			em.persist(l);
   		}
   		
    	Bairro b = null;
    	try {
    		b = bU.buscarBairroExato(reCliente.getBairro().getNome());
    		em.merge(b);
    	} catch (NoResultException n){
    		b = new Bairro();
    		b.setNome(reCliente.getBairro().getNome());
    		em.persist(b);
    	}
    	
    	Cidade cid;
    	try {
    		cid = bU.buscarCidadeExato(reCliente.getCidade().getNome());
    		em.merge(cid);
    	} catch (NoResultException n){
    		cid = new Cidade();
    		cid.setNome(reCliente.getCidade().getNome());
    		em.persist(cid);
    	}

    	// Desnecessário procurar estado, enquanto o software não sair do RJ (Eh, eh!).
    	Estado e = bU.buscarEstadoExato("RIO DE JANEIRO");
    	em.merge(e);
    	RegiaoEndereco re = new RegiaoEndereco(t, l, b, cid, e);

    	RegiaoEndereco reReal = null;
    	try {
    		reReal = bU.buscarRegioesEnderecosExato(re);
    		em.merge(reReal);
    	} catch (NoResultException n){
    		reReal = re;
    		em.persist(reReal);
    	}

    	cliente.getEndereco().setRegiaoEndereco(reReal);
    	if (cliente.getId() == null){
    		em.persist(cliente);
    	} else {
    		em.merge(cliente);
    	}
	}

Como uso o Struts2, uso a função de preenchimento de todo o gráfico do objeto. Por isso verifico se o logradouro, bairro e cidade já existem para incluí-los ou não.

Pois bem, depois de me alongar desse jeito, quando preciso incluir um dos valores (bairro, cidade, etc.) no código, é disparado o erro abaixo:

SEVERE: Servlet.service() for servlet default threw exception
javax.persistence.RollbackException: Transaction marked as rollbackOnly
	at org.hibernate.ejb.TransactionImpl.commit(TransactionImpl.java:51)
	at org.springframework.orm.jpa.JpaTransactionManager.doCommit(JpaTransactionManager.java:456)
	at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:709)
	at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:678)
	at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:321)
	at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:116)
	at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:171)
	at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:204)
	at $Proxy24.salvar(Unknown Source)
	at br.com.pizzaria.servico.ClientesServico.salvar(ClientesServico.java:32)
	at br.com.pizzaria.acoes.ClientesCRUDAction.salvar(ClientesCRUDAction.java:40)
	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)

Todo este gráfico está marcado com o CascadeType.ALL. Eu sei que o setRollbackOnly é disparado somente quando uma exceção não-checada é lançada. Mas no log não aparece nada! Existe alguma outra possibilidade da transação ser marcada para rollBackOnly()?

Alguém tem alguma pista?

Muito obrigado pela paciência e desculpem pelo testamento. Estou no desespero e não queria mudar muito a linha de raciocínio.

1 Resposta

E
Galera, me ajuda aí!

 Valeu.
Criado 17 de maio de 2008
Ultima resposta 27 de mai. de 2008
Respostas 1
Participantes 1