Exception lançada ao tentar persistir objeto em cascata Hibernate

Bom dia amigos,

Estou com um problema na persistência de objetos em cascata usando o Hibernate.

Quando mando persistir um objeto é lançada a Exception: ServletException org.hibernate.AssertionFailure: null id in model.beans.Assessor entry (don’t flush the Session after an exception occurs)

Vejam como está meu mapeando através de Annotations

@Entity
@Table(name = "assessores")
public class Assessor implements Serializable {

	private static final long serialVersionUID = 8156212227013079327L;
	@Column(name = "id_assessor")
	@Id
	@GeneratedValue
	private Integer id;
	private String nome;
	@Column(name = "data_nascimento")
	private String dataNascimento;
	@Column(name="estado_civil")
	private String estadoCivil;
	private String rg;
	@Column(name="orgao_emissor")
	private String orgaoEmissor;
	private String cpf;
	@OneToOne(cascade=CascadeType.PERSIST)
	@JoinColumn(name = "id_dados_eleitorais")
	private DadosEleitorais dadosEleitorais;
	@Column(name = "telefone_residencial")
	private String telefoneResidencial;
	@Column(name = "telefone_celular")
	private String telefoneCelular;
	@OneToOne(cascade=CascadeType.PERSIST)
	@JoinColumn(name = "id_endereco")
	private Endereco endereco;
	@OneToOne(cascade=CascadeType.PERSIST)
	@JoinColumn(name = "id_cargo")
	private Cargo cargo;
	private Calendar data_admissao;
	private Boolean ativo;

Agradeço qualquer ajuda

Abraços

Pela descrição da sua exceção, isso parece uma exceção que vem depois do problema de verdade, tem algo antes dessa exceção na sua stacktrace?

Olá DigaoNeves

O resultado completo no console é:

org.hibernate.AssertionFailure: null id in model.beans.Assessor entry (don't flush the Session after an exception occurs) at org.hibernate.event.def.DefaultFlushEntityEventListener.checkId(DefaultFlushEntityEventListener.java:82) at org.hibernate.event.def.DefaultFlushEntityEventListener.getValues(DefaultFlushEntityEventListener.java:190) at org.hibernate.event.def.DefaultFlushEntityEventListener.onFlushEntity(DefaultFlushEntityEventListener.java:147) at org.hibernate.event.def.AbstractFlushingEventListener.flushEntities(AbstractFlushingEventListener.java:219) at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:99) at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50) at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1216) at org.hibernate.impl.SessionImpl.managedFlush(SessionImpl.java:383) at org.hibernate.transaction.JDBCTransaction.commit(JDBCTransaction.java:133) at persistence.ConexaoHibernateFilter.doFilter(ConexaoHibernateFilter.java:73) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:344) at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.invoke(FilterSecurityInterceptor.java:110) at org.springframework.security.web.access.intercept.FilterSecurityInterceptor.doFilter(FilterSecurityInterceptor.java:84) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:356) at org.springframework.security.web.access.ExceptionTranslationFilter.doFilter(ExceptionTranslationFilter.java:98) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:356) at org.springframework.security.web.session.SessionManagementFilter.doFilter(SessionManagementFilter.java:95) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:356) at org.springframework.security.web.authentication.AnonymousAuthenticationFilter.doFilter(AnonymousAuthenticationFilter.java:79) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:356) at org.springframework.security.web.servletapi.SecurityContextHolderAwareRequestFilter.doFilter(SecurityContextHolderAwareRequestFilter.java:55) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:356) at org.springframework.security.web.savedrequest.RequestCacheAwareFilter.doFilter(RequestCacheAwareFilter.java:36) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:356) at org.springframework.security.web.authentication.www.BasicAuthenticationFilter.doFilter(BasicAuthenticationFilter.java:178) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:356) at org.springframework.security.web.authentication.ui.DefaultLoginPageGeneratingFilter.doFilter(DefaultLoginPageGeneratingFilter.java:91) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:356) at org.springframework.security.web.authentication.AbstractAuthenticationProcessingFilter.doFilter(AbstractAuthenticationProcessingFilter.java:188) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:356) at org.springframework.security.web.authentication.logout.LogoutFilter.doFilter(LogoutFilter.java:106) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:356) at org.springframework.security.web.context.SecurityContextPersistenceFilter.doFilter(SecurityContextPersistenceFilter.java:80) at org.springframework.security.web.FilterChainProxy$VirtualFilterChain.doFilter(FilterChainProxy.java:356) at org.springframework.security.web.FilterChainProxy.doFilter(FilterChainProxy.java:150) at org.springframework.web.filter.DelegatingFilterProxy.invokeDelegate(DelegatingFilterProxy.java:237) at org.springframework.web.filter.DelegatingFilterProxy.doFilter(DelegatingFilterProxy.java:167) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:233) at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:191) at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:127) at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:102) at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:109) at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:298) at org.apache.coyote.http11.Http11AprProcessor.process(Http11AprProcessor.java:864) at org.apache.coyote.http11.Http11AprProtocol$Http11ConnectionHandler.process(Http11AprProtocol.java:579) at org.apache.tomcat.util.net.AprEndpoint$Worker.run(AprEndpoint.java:1665) at java.lang.Thread.run(Unknown Source)

Debuga seu código. vai ter um momento que dispara uma exception, e antes do commit/flush.

Olá Jakefrog,

Debuguei o meu código e a exception é lançada justamente no momento do commit.

O meu commit está nesse filter

public class ConexaoHibernateFilter implements Filter {

	private SessionFactory sf;

	public void init(FilterConfig config) throws ServletException {
		this.sf = HibernateUtil.getSessionFactory();
	}

	public void destroy() {
	}

	public void doFilter(ServletRequest servletRequest,
			ServletResponse servletResponse, FilterChain chain)
			throws ServletException {

		try {

			this.sf.getCurrentSession().beginTransaction();

			chain.doFilter(servletRequest, servletResponse);

			Transaction transaction = this.sf.getCurrentSession().getTransaction();
			transaction.commit();
			this.sf.getCurrentSession().close();

		} catch (Throwable ex) {
			try {
				if (this.sf.getCurrentSession().getTransaction().isActive()) {
					this.sf.getCurrentSession().getTransaction().rollback();
					ex.printStackTrace();
				}
			} catch (Throwable t) {
				t.printStackTrace();
			}
			throw new ServletException(ex);
		}
	}

}

De qualquer forma não entendo por que o commit só não dá certo quando tenho dados em cascata.

Quando você tem dados para salvar com o cascade dentro do chain.doFilter(servletRequest, servletResponse); não levanta nenhuma exception? Veja c não está acontecendo alguma exception lá dentro.

JakeFrog,

A única exception lançada é na hora do commit.

Não está ocorrendo exception dentro do doFilter.

:roll:

É cara, bizarro isso aí.

Tente aumenta o nível de debug do se log.

Pode ser que tenha alguma outra exception estourando aí que não está sendo exibida.

prog.tiago,

Tenta completar a annotation @GeneratedValue com o atributo strategy, exemplo:

@GeneratedValue (strategy = GenerationType.AUTO)
    private Integer id; 

[quote=jakefrog]É cara, bizarro isso aí.

Tente aumenta o nível de debug do se log.

Pode ser que tenha alguma outra exception estourando aí que não está sendo exibida.[/quote]

Eu tenho que concordar com o jakefrog. Não querendo parecer insistente ou teimoso, mas a sua exceção é lançada exatamente por causa disso, você está dando flush() em uma Sessão, sendo que nela ocorreu alguma exceção.

Verifique blocos try/catch, ou aumente o nível de log para imprimir tudo, se possível, pode ser que alguma exceção esteja sendo engolida por aí.

[quote=digaoneves][quote=jakefrog]É cara, bizarro isso aí.

Tente aumenta o nível de debug do se log.

Pode ser que tenha alguma outra exception estourando aí que não está sendo exibida.[/quote]

Eu tenho que concordar com o jakefrog. Não querendo parecer insistente ou teimoso, mas a sua exceção é lançada exatamente por causa disso, você está dando flush() em uma Sessão, sendo que nela ocorreu alguma exceção.

Verifique blocos try/catch, ou aumente o nível de debug se possível, pode ser que alguma exceção esteja sendo engolida por aí.[/quote]

Realmente tá estranho… :shock:

Vou debugar mais a fundo, e posto aqui o resultado.

Abraços

Olá amigos,

Reservei esse sabadão para tentar resolver essa pendência.

Debugando o código mais a fundo percebi que era lançada um exception internamente quando o método commit tentava dar um flush.

Bem aqui:

[code]public void managedFlush() {
if ( isClosed() ) {
log.trace( “skipping auto-flush due to session closed” );
return;
}
log.trace(“automatically flushing session”);
flush();

	if ( childSessionsByEntityMode != null ) {
		Iterator iter = childSessionsByEntityMode.values().iterator();
		while ( iter.hasNext() ) {
			( (Session) iter.next() ).flush();
		}
	}
}[/code]

Seguindo a dica do Urubatan em http://www.urubatan.com.br/dica-rapida-desabilitando-a-persistencia-automatica-no-hibernate/, desabilitei a persistência automática.

Eis que a exception parou de ser lançada, no entanto meu objeto não é mais persistido.

Curiosamente, tenho um objeto pai e 4 objetos filhos. Um objeto filho ainda é persistido, os outros não.

Vejam meu código:

public void adicionaAssessor(){
		
		
		Endereco endereco=new Endereco();
		endereco.setAtivo(true);
		endereco.setBairro("Jardim Represa");
		endereco.setCep("09842-080");
		endereco.setMunicipio("São Bernardo do Campo");
		endereco.setNumero("409");
		endereco.setRua("Estrada Galvão Bueno");
		endereco.setUf("SP");
		
		Cargo cargo=new Cargo();
		cargo.setCargo("Gerente2");
		
		
		ZonaEleitoral zona=new ZonaEleitoral();
		zona.setCodigoProcessual("44");
		zona.setEndereco(endereco);
		zona.setNumeroZona(433);
		
		
		
		DadosEleitorais dadosEleitorais=new DadosEleitorais();
		dadosEleitorais.setAtivo(true);
		dadosEleitorais.setFiliacaoPartidaria(new PartidoDAO().busca(28));
		dadosEleitorais.setTituloEleitor("44444");
		dadosEleitorais.setZonaEleitoral(zona);
		
		
		Assessor assessor=new Assessor();
		assessor.setNome("Orlando da Silva");
		assessor.setDataNascimento("15/12/1995");
		assessor.setEstadoCivil("solteiro");
		assessor.setRg("48.121.692-3");
		assessor.setOrgaoEmissor("SSP");
		assessor.setCpf("386.873.828-20");
		assessor.setDadosEleitorais(dadosEleitorais);
		assessor.setTelefoneResidencial("4342-5395");
		assessor.setTelefoneCelular("7169-3668");
		assessor.setCargo(cargo);
		assessor.setData_admissao(Calendar.getInstance());
		assessor.setEndereco(endereco);
		assessor.setAtivo(true);
		
		AssessorService s=new AssessorService();
		s.adiciona(assessor);
	}

Dentro dos objetos filhos, apenas o cargo é persistido. :roll:

Como pode???

Vejam meus relacionamentos:

[code]@Entity
@Table(name = “assessores”)
public class Assessor implements Serializable {

private static final long serialVersionUID = 8156212227013079327L;
@Column(name = "id_assessor")
@Id
@GeneratedValue
private Integer id;
private String nome;
@Column(name = "data_nascimento")
private String dataNascimento;
@Column(name="estado_civil")
private String estadoCivil;
private String rg;
@Column(name="orgao_emissor")
private String orgaoEmissor;
private String cpf;
@OneToOne(cascade=CascadeType.ALL)
@JoinColumn(name = "id_dados_eleitorais")
private DadosEleitorais dadosEleitorais;
@Column(name = "telefone_residencial")
private String telefoneResidencial;
@Column(name = "telefone_celular")
private String telefoneCelular;
@OneToOne(cascade=CascadeType.ALL)
@JoinColumn(name = "id_endereco")
private Endereco endereco;
@OneToOne(cascade=CascadeType.ALL)
@JoinColumn(name = "id_cargo")
private Cargo cargo;
private Calendar data_admissao;
private Boolean ativo;
private byte[] foto;[/code]

Confesso que não estou entendendo o que está acontecendo. :?: :?:

Fico grato pela ajuda!

Olá amigos,

Esse último problema foi resolvido. Era apenas um erro grosseiro de mapeamento.

Obrigado e boa semana à vocês.

Viva ao Hibernate!