[RESOLVIDO] Spring + Hibernate - problema com controle de transações

5 respostas
calel

Durante um teste com JUnit tento incluir no banco de dados uma campanha e logo após incluo um agendamento que possui uma FK para essa campanha. Nesse momento recebo o erro que a campanha especificada não foi encontrada...
Se puderem me ajudar agradeço!

javax.persistence.EntityNotFoundException: Unable to find com.projeto.model.Campanha with id 9999
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"/META-INF/beans.xml"})
public class AgendamentoFacadeTest {
	@Autowired
	private AgendamentoFacade agendamentoFacade;
	@Autowired
	private CampanhaFacade campanhaFacade;
	
	@Test
	public void testGeraAgendamentoAtravesDeCampanhaDBM(){
		String codCampanha = "9999";
		
		CampanhaDBM campanhaDBM = campanhaFacade.obtemCampanhaPorCodigo(codCampanha);
		Campanha campanha = new Campanha(campanhaDBM);
		campanha = campanhaFacade.salvar(campanha);
		Integer template = 1;
		Integer sender = 1;
		String nomeAgendamento = "Um nome de agendamento";
		String nomeRemetente = "Um nome legal de remetente";
		String enderecoParaResposta = "[email removido]";
		
		Agendamento agendamento = new Agendamento(campanha, template, sender, nomeAgendamento, nomeRemetente, enderecoParaResposta);
		
		Agendamento ag = agendamentoFacade.salvar(agendamento); //<-- aqui ocorre o erro
		
		Assert.assertNotNull("O agendamento não foi persistido.", ag);
	}
}
@Repository
public class BaseDAO {
	private JpaTemplate jpaTemplate;
	
	@PersistenceUnit
	public void setJpaTemplate(EntityManagerFactory emf) {
		EntityManager em = emf.createEntityManager();
		em.setFlushMode(FlushModeType.COMMIT);
		this.jpaTemplate = new JpaTemplate(em);
	}

	protected Session getSession(){
		
		return (Session) jpaTemplate.getEntityManager().getDelegate();
	}
}
@Service
public class CampanhaFacadeImpl implements CampanhaFacade {
	@Autowired
	private CampanhaDAO campanhaDAO;

	@Override @Transactional
	public <T> T salvar(T campanha) {
		return campanhaDAO.salvar(campanha);
	}

}
@Repository
public class CampanhaDAOImpl extends BaseDAO implements CampanhaDAO {
	public <T> T salvar(T campanha) {
		campanha = (T) getSession().merge(campanha);
		return campanha;
	}

}
@Service
public class AgendamentoFacadeImpl implements AgendamentoFacade {
	@Autowired
	private AgendamentoDAO agendamentoDAO;

	@Override @Transactional
	public Agendamento salvar(Agendamento agendamento) {
		return agendamentoDAO.salvar(agendamento);
	}

}
@Repository
public class AgendamentoDAOImpl extends BaseDAO implements AgendamentoDAO{

	@Override
	public Agendamento salvar(Agendamento agendamento) {
		return (Agendamento) getSession().merge(agendamento);
	}

}
<beans xmlns="http://www.springframework.org/schema/beans"
	xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
	xmlns:aop="http://www.springframework.org/schema/aop"
	xmlns:context="http://www.springframework.org/schema/context"
	xmlns:tx="http://www.springframework.org/schema/tx"
	xmlns:p="http://www.springframework.org/schema/p"
	xsi:schemaLocation="http://www.springframework.org/schema/beans
           http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
           http://www.springframework.org/schema/aop
           http://www.springframework.org/schema/aop/spring-aop-2.5.xsd
           http://www.springframework.org/schema/context
           http://www.springframework.org/schema/context/spring-context-2.5.xsd
           http://www.springframework.org/schema/tx
           http://www.springframework.org/schema/tx/spring-tx-2.5.xsd">

	<context:component-scan base-package="com.projeto" />
      
	<!-- bean post-processor for JPA annotations -->
	<bean class="org.springframework.orm.jpa.support.PersistenceAnnotationBeanPostProcessor"/>	
	
	<bean id="entityManagerFactory" class="com.projeto.dao.creator.JPAEntityManagerCreator">
	</bean>
	
	<bean id="transactionManager" class="org.springframework.orm.jpa.JpaTransactionManager"
      p:entityManagerFactory-ref="entityManagerFactory"/>

	<tx:annotation-driven/>

</beans>

5 Respostas

Hebert_Coelho

Faça um flush antes de chamar o segundo salvar.

calel

obrigado jakefrog, não ocorreu mais o erro.
existe um meio do spring ou hibernate controlar isso? ou nesse caso o unico meio é utilizando o flush manual mesmo?

Achei estranho também que se eu não colocar um flush depois de salvar um agendamento, essa informação não é gravada no banco de dados… Existe alguma configuração que esqueci de fazer e por esse motivo esses dados não são gravados?

Hebert_Coelho

Cara, infelizmente não tenho como te ajudar com as Transações em Spring.

Não entendo desse cara.

Uma coisa eu sei, que tem como o servidor controlar a transação ou sua aplicação fazer esse trabalho sujo.

Não sei como você arquitetou isso em seu sistema, mas valeria a pena estudar melhor transações no Spring. [=

calel

Irei pesquisar mais sobre o assunto, muito obrigado pela ajuda!

calel

Demorou um tempo mas descobri o problema.

Estava injetando um EntityManagerFactory para me aproveitar do scan da JPA nas classes entity, e usando o getDelegate para trabalhar com o Hibernate, e é nessa hora que o Spring parava de controlar a transação. Para que o controle de transações do Spring funcione adequadamente tenho duas alternativas, injetar diretamente um EntityManager e utilizar JPA na minha aplicação, ou se quiser continuar a utilizar o Hibernate, devo injetar uma SessionFactory e definir no xml as classes da minha aplicação.

Com essa solução antes de efetuar o commit o Spring executa um flush resolvendo meu problema.

Criado 16 de janeiro de 2012
Ultima resposta 25 de jan. de 2012
Respostas 5
Participantes 2