[RESOLVIDO] vRaptor - ao listar exibe mais de uma vez o mesmo objeto

Boa noite galera!

to com um probleminha aqui… decorrente da solução que achei anteriormente em outro tópico: http://www.guj.com.br/java/284940-erro-em-relacionamento

seguinte, o objeto Debito possui uma lista de objetos MeioDepositoOrigemDebito, e ao listar (mostrar na tela) cada objeto Debito, ele eh exibido a mesma quantidade de vezes que o numero de objetos na lista de MeioDepositoOrigemDebito!!

no banco existe apenas um registro de cada Debito… e na tela mostra desse jeito…

Alguém já teve este problema?

soh pra complementar:

  • no banco nao existem registros duplicados
  • a duplicaçao ocorre ao recuperar a lista de debitos, ou seja, a partir do seguinte método o objeto Debito já eh retornado duplicado na lista:public List<Debito> listarPorCenario(Long id){ return this.session.createCriteria(Debito.class).add(Restrictions.eq("idCenario", id)).list(); }
    mas essa mesma estrutura do método eh usado para recuperar outras listas e nao duplica os outros objetos dessas listas…

vc tem algum fetch=…EAGER nessa classe Debito?

Eai Lucas!

Cara, vou postar a minha classe Debito pra vc dar uma olhada:[code]@Entity
public class Debito extends Valor implements Serializable {

@NotNull(message="A operaçao necessaria deve ser informada!")
private Boolean operacaoNecessaria;

@ManyToOne
@NotNull(message="O meio de debito deve ser informado!")
private MeioDebito meioDebito;

@OneToMany(cascade = CascadeType.ALL, fetch = FetchType.EAGER, orphanRemoval = false)
@NotNull(message="O meio de deposito de origem do debito deve ser informado!")
private List<MeioDepositoOrigemDebito> listaMeioDepositoOrigemDebito;

private Boolean snEntrada;

public Debito(){
}

//getters and setters

}[/code]
Tem um EAGER sim… isso eh um problema?

eh, pq ele vai fazer um join pra poder buscar esse cara…

algum motivo forte pra ter esse EAGER? em geral deixar cascade=ALL também é errado, eh isso mesmo que vc quer?

bem… vamos por partes…

  • o EAGER eh pra carregar a lista quando o Debito for carregado, certo? Se sim, entao nao preciso disso
  • o cascade=ALL precisa pq essa lista vai ser persistida no mesmo momento em que o Debito for persistido, e a lista sera excluida quando o Debito for excluido…

respondi a sua pergunta?

tire o eager, e se vc precisa do cascade pra PERSIST, deixe soh o cascade pra PERSIST, e nao o ALL :wink:

mas o cascade PERSIST também vai excluir em cascata a lista de objetos MeioDepositoOrigemDebito?

nao… soh vai fazer a operaçao em cascata pro persist… pra fazer pro remove tb vc faz:


@....(cascade={...PERSIST, ....REMOVE}...)

eu fiz como vc disse Lucas, tirei o EAGER e o cascade.ALL@OneToMany(cascade = {CascadeType.PERSIST,CascadeType.REMOVE}, orphanRemoval = false) @NotNull(message="O meio de deposito de origem do debito deve ser informado!") private List<MeioDepositoOrigemDebito> listaMeioDepositoOrigemDebito;
mas deu esse erro agora:19/10/2012 18:30:05 org.apache.catalina.core.StandardWrapperValve invoke GRAVE: Servlet.service() for servlet default threw exception br.com.caelum.vraptor.InterceptionException: exception raised, check root cause for details: org.springframework.dao.InvalidDataAccessApiUsageException: object references an unsaved transient instance - save the transient instance before flushing: br.com.website.bean.MeioDepositoOrigemDebito; nested exception is org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: br.com.website.bean.MeioDepositoOrigemDebito at br.com.caelum.vraptor.interceptor.ExecuteMethodInterceptor.intercept(ExecuteMethodInterceptor.java:96) at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54) at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54) at br.com.caelum.vraptor.core.LazyInterceptorHandler.execute(LazyInterceptorHandler.java:61) at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54) at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:56) at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54) at br.com.caelum.vraptor.interceptor.FlashInterceptor.intercept(FlashInterceptor.java:83) at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54) at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54) at br.com.caelum.vraptor.interceptor.ExceptionHandlerInterceptor.intercept(ExceptionHandlerInterceptor.java:71) at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54) at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54) at br.com.caelum.vraptor.interceptor.InstantiateInterceptor.intercept(InstantiateInterceptor.java:48) at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54) at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54) at br.com.caelum.vraptor.interceptor.ParametersInstantiatorInterceptor.intercept(ParametersInstantiatorInterceptor.java:87) at br.com.caelum.vraptor.core.LazyInterceptorHandler.execute(LazyInterceptorHandler.java:59) at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54) at br.com.caelum.vraptor.interceptor.ResourceLookupInterceptor.intercept(ResourceLookupInterceptor.java:69) at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:54) at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54) at br.com.caelum.vraptor.core.ToInstantiateInterceptorHandler.execute(ToInstantiateInterceptorHandler.java:56) at br.com.caelum.vraptor.core.DefaultInterceptorStack.next(DefaultInterceptorStack.java:54) at br.com.caelum.vraptor.core.EnhancedRequestExecution.execute(EnhancedRequestExecution.java:44) at br.com.caelum.vraptor.VRaptor$1.insideRequest(VRaptor.java:92) at br.com.caelum.vraptor.ioc.spring.SpringProvider.provideForRequest(SpringProvider.java:58) at br.com.caelum.vraptor.VRaptor.doFilter(VRaptor.java:89) at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:235) at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:206) at org.springframework.orm.hibernate3.support.OpenSessionInViewFilter.doFilterInternal(OpenSessionInViewFilter.java:198) at org.springframework.web.filter.OncePerRequestFilter.doFilter(OncePerRequestFilter.java:76) 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.Http11Processor.process(Http11Processor.java:859) at org.apache.coyote.http11.Http11Protocol$Http11ConnectionHandler.process(Http11Protocol.java:588) at org.apache.tomcat.util.net.JIoEndpoint$Worker.run(JIoEndpoint.java:489) at java.lang.Thread.run(Thread.java:680) Caused by: org.springframework.dao.InvalidDataAccessApiUsageException: object references an unsaved transient instance - save the transient instance before flushing: br.com.website.bean.MeioDepositoOrigemDebito; nested exception is org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: br.com.website.bean.MeioDepositoOrigemDebito at org.springframework.orm.hibernate3.SessionFactoryUtils.convertHibernateAccessException(SessionFactoryUtils.java:654) at org.springframework.orm.hibernate3.HibernateTransactionManager.convertHibernateAccessException(HibernateTransactionManager.java:793) at org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:664) at org.springframework.transaction.support.AbstractPlatformTransactionManager.processCommit(AbstractPlatformTransactionManager.java:754) at org.springframework.transaction.support.AbstractPlatformTransactionManager.commit(AbstractPlatformTransactionManager.java:723) at org.springframework.transaction.interceptor.TransactionAspectSupport.commitTransactionAfterReturning(TransactionAspectSupport.java:393) at org.springframework.transaction.interceptor.TransactionInterceptor.invoke(TransactionInterceptor.java:120) at org.springframework.aop.framework.ReflectiveMethodInvocation.proceed(ReflectiveMethodInvocation.java:172) at org.springframework.aop.framework.JdkDynamicAopProxy.invoke(JdkDynamicAopProxy.java:202) at $Proxy55.incluir(Unknown Source) at br.com.website.controller.DebitoController.incluir(DebitoController.java:145) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) at java.lang.reflect.Method.invoke(Method.java:597) at br.com.caelum.vraptor.interceptor.ExecuteMethodInterceptor.intercept(ExecuteMethodInterceptor.java:61) ... 43 more Caused by: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: br.com.website.bean.MeioDepositoOrigemDebito at org.hibernate.engine.ForeignKeys.getEntityIdentifierIfNotUnsaved(ForeignKeys.java:243) at org.hibernate.type.EntityType.getIdentifier(EntityType.java:456) at org.hibernate.type.ManyToOneType.nullSafeSet(ManyToOneType.java:121) at org.hibernate.persister.collection.AbstractCollectionPersister.writeElement(AbstractCollectionPersister.java:815) at org.hibernate.persister.collection.AbstractCollectionPersister.recreate(AbstractCollectionPersister.java:1203) at org.hibernate.action.CollectionRecreateAction.execute(CollectionRecreateAction.java:58) at org.hibernate.engine.ActionQueue.execute(ActionQueue.java:273) at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:265) at org.hibernate.engine.ActionQueue.executeActions(ActionQueue.java:188) at org.hibernate.event.def.AbstractFlushingEventListener.performExecutions(AbstractFlushingEventListener.java:321) at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:51) 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 org.springframework.orm.hibernate3.HibernateTransactionManager.doCommit(HibernateTransactionManager.java:656) ... 56 more

nunca vi esse erro antes…

se vc deu save no Debito e ele tem cascade persist, nao deveria acontecer isso…

esse @OneToMany sem mappedBy eh de propósito?

Precisa do mappedBy?
Esse seria o motivo do erro?

Lucas, eu fiz assim e funcionou certinho:@OneToMany(cascade = CascadeType.ALL, orphanRemoval = false) @NotNull(message="O meio de deposito de origem do debito deve ser informado!") private List<MeioDepositoOrigemDebito> listaMeioDepositoOrigemDebito;

apenas substitui o cascade = {CascadeType.PERSIST,CascadeType.REMOVE} por cascade = CascadeType.ALL

estranho neh?!