[RESOLVIDO]Dúvida com Mapeamente e uso de Collection

14 respostas
Diego_Adriano

Bem galera, estou com um enorme problema na hora de mapear minhas tabelas, acho que estou fazendo de forma errado pois não consigo exibir os dados na tela.
Bem vms lá, tenho a tabela TreinoGeral com um mapeamento que indica que "1" treino pode ter vários "Dados" de exercícios, esta correto?

public class TreinoGeral implements Serializable{

	@Id@GeneratedValue(strategy=GenerationType.AUTO)
	private Long id;
	private int sessoestotal;
	private int sessoesrealizadas;
	private int sessoesrestantes;
		
	@ManyToOne
	private Cliente cliente;
	
	@OneToMany
	@JoinTable(name="treino_dados",
	 joinColumns=@JoinColumn(name="treino_tados"),
	 inverseJoinColumns=@JoinColumn(name="dados_id"))
	private Collection<DadosExercicio> dadostreino;
public class DadosExercicio implements Serializable{

	@Id @GeneratedValue(strategy=GenerationType.AUTO)
	private Long id;
	private int peso;
	private int repeticao;
	private int descanso;
	private int serie;
	private boolean imprime;
	private int variacao;

	@OneToOne
	@JoinColumn(name="exercicio")
	private Exercicio exercicio;
	
	@ManyToOne
	@JoinColumn(name="treinogeral")
	private TreinoGeral treinogeral;

Bem, não sei se estou vendo de forma correta para fazer o mapeamento pois nunca utilizei o Collection se alguem puder me ajudar agradeço.

14 Respostas

Hebert_Coelho

Se seu problema é na hora de exibir, você tem certeza de que você tem os dados na tabela?

Como você está fazendo para exibir?

Então mapeie como se fosse um List. O mapeamento vai continuar a mesma coisa.

Talvez esse post te ajude: @OneToMany e @ManyToOne Unidirecional e Bidirecional.

fbl.lucas

Cara ta errado isso ai. Não deveria ter esse @JoinTable

@OneToMany(mappedby = "treinogeral") private Collection<DadosExercicio> dadostreino;

Diego_Adriano

Então jakefrog, leio bastantes seus Posts, que são ótimos diga-se de passagem ..
Então, estava testando isso mesmo, não esta sendo carregado na tabela.
Talvez possa ser a forma que eu esteja fazendo.
Esta assim o código:

Construtor:
public DadosExercicio(int peso, int repeticao, int descanso, Exercicio exercicio,
			int variacao, int serie) {
	
		this.peso = peso;
		this.repeticao = repeticao;
		this.descanso = descanso;
		this.exercicio = exercicio;
		this.variacao = variacao;
		this.serie = serie;
	}
No Bean:
private List<DadosExercicio> dados;
private DadosExercicio treinoDados;
//construtor
public TreinoBean() {
		
	dados = new ArrayList<DadosExercicio>();
        treinoDados = new DadosExercicio();		
}
public void adicionatreino(){
		
 List<DadosExercicio> de = new ArrayList<DadosExercicio>();//COLOQUEI PARA FAZER UM TESTE
		
	de.add(new DadosExercicio(treinoDados.getPeso(), treinoDados.getRepeticao(), treinoDados.getDescanso(), treinoDados.getExercicio(), treinoDados.getVariacao(),treinoDados.getSerie()));
		setDados(de);	
}
E na view:
<p:dataTable id="detalhes"
								 value="#{treinoBean.dados}"
								 var="treino"
								 rows="12"
								 paginator="true">
						
						<p:column headerText="Variação">
							<h:outputText value="#{treino.variacao}"/>
						</p:column>
						
						<p:column headerText="Exercicio">
							<h:outputText value="#{treino.exercicio.nome}"/>
						</p:column>
						
						<p:column headerText="Séries">
							<h:outputText value="#{treino.serie}"/>
						</p:column>
						
						<p:column headerText="Repetições">
							<h:outputText value="#{treino.repeticao}"/>
						</p:column>
						
						<p:column headerText="Peso">
							<h:outputText value="#{treino.peso}"/>
						</p:column>
						
						<p:column headerText="Descanso">
							<h:outputText value="#{treino.descanso}"/>	
						</p:column>
						
					</p:dataTable>

Ele exibe somente o nome do Exercício, o restante é exibido " 0 "

Diego_Adriano

Beleza Lucas, vou testar como sugeriu.

Hebert_Coelho

Opa, valeu.

Vc deixou DadosExercicio com um construtor padrão? Sem argumentos?

Como você está carregando seu objeto do banco de dados?

Diego_Adriano

Sim sim, deixei o construto sem Argumentos;
Estão vindo da View

<h:outputText value="Sessões: "/>
<p:inputText value="#{treinoBean.treinoGeral.sessoestotal}" size="3"/>
<p:column></p:column>
					
<h:outputText value="Variação: "/>
<p:inputText value="#{treinoBean.variacao}" size="5">
    <p:ajax event="blur" update="dadosGerais:varia" listener="#{treinoBean.carregavariacoes}"/>
</p:inputText>
<p:column></p:column>
					
<h:outputText value="Cliente: "/>
<p:inputText value="#{treinoBean.treinoGeral.cliente.nome}"
				 id="cliente"/>
<p:commandButton icon="ui-icon-search" ajax="true" oncomplete="janelaCliente.show()"
			 update="tabelaCliente"/>
					
<h:outputText value="Exercicio: "/>
<p:inputText value="#{treinoBean.treinoDados.exercicio.nome}"
		 id="exercicio"/>
<p:commandButton icon="ui-icon-search" ajax="true" oncomplete="janelaExercicios.show()"
			 update="tabelaExercicios"/>			 
											
<h:outputText value="Variação: "/>
<p:selectOneMenu value="#{treinoBean.treinoDados.variacao}"
				 id="varia">
	<f:selectItem itemLabel="Escolha a Variação" itemValue="" />  
     	<f:selectItems value="#{treinoBean.variacoes}" /> 
		</p:selectOneMenu>	
<p:column></p:column>
						
<h:outputText value="Séries: "/>
<p:inputText value="#{treinoBean.treinoDados.serie}" size="3"/>
<p:column></p:column>
						
<h:outputText value="Repetição: "/>
<p:inputText value="#{treinoBean.treinoDados.repeticao}" size="3"/>
<p:column></p:column>
						
<h:outputText value="Peso: "/>
<p:inputText value="#{treinoBean.treinoDados.peso}" size="3"/>
<p:column></p:column>
						
<h:outputText value="Descanso: "/>
<p:inputText value="#{treinoBean.treinoDados.descanso}" size="5"/>
						
</h:panelGrid>
					
<h:panelGrid>
	<p:column>
		<p:commandButton update="tblTreino, dadosGerais" icon="ui-icon-plus"
					action="#{treinoBean.adicionatreino}" ajax="false" immediate="true"/>
	</p:column>
</h:panelGrid>

A unica coisa que difere do Exercício é que ele vem de outro DataTable.

Diego_Adriano

Bom Galera, consegui resolver o problema, ficou da seguinte forma:

Table:
@OneToMany(mappedBy = "treinogeral") 
private List<DadosExercicio> dadostreino;
	
public TreinoGeral() {
	// TODO Auto-generated constructor stub
}
	
public TreinoGeral(int sessoestotal,int sessoesrealizadas,int sessoesrestantes,
		Cliente cliente, List<DadosExercicio> dadostreino) {
	this.sessoestotal = sessoestotal;
	this.sessoesrealizadas = sessoesrealizadas;
	this.sessoesrestantes = sessoesrestantes;
	this.cliente = cliente;
	this.dadostreino = dadostreino;
}
Bean:
DadosExercicio de = new DadosExercicio(treinoDados.getPeso(), treinoDados.getRepeticao(), treinoDados.getDescanso(),
		treinoDados.getExercicio(), treinoDados.getVariacao(),treinoDados.getSerie());
		
       treinoDados = new DadosExercicio();
		
	getDados().add(de);
	treinoGeral.setDadosTreino(dados);
Agora minha dúvida, como irei fazer para Inserir o ID do TreinoGeral na table de DadosExercicio? Fiz dessa forma para testar se estava salvando, porém vai vazio o "ID" de relacionamento:
public void SalvarTreinoG(TreinoGeral tg){
		
	this.entityManager.persist(tg);
	this.entityManager.flush();
		
	SalvarTreinoD(tg.getDadosTreino());
		
}
public void SalvarTreinoD(List<DadosExercicio> dados){


	for (DadosExercicio td : dados){
			
		if (td.getVariacao() == 1){
			td.setImprime(true);
			
		}else{
			td.setImprime(false);
		}
			
	this.entityManager.persist(td);
	this.entityManager.flush();
			
     }
		
}
SQL:
id, descanso, imprime, peso, repeticao, serie, variacao, exercicio, treinogeral
 1,          10,           b,     35,           12,      3,           1,            2,       null
 2,            3,           b,     25,            3,       2,           2,            1,       null
 3,            2,           b,     25,          33,       2,           3,            5,       null
 4,            1,           b,       3,            2,       1,          2,             3,       null
fbl.lucas
DadosExercicio de = new DadosExercicio(treinoDados.getPeso(), treinoDados.getRepeticao(), treinoDados.getDescanso(),
		treinoDados.getExercicio(), treinoDados.getVariacao(),treinoDados.getSerie());
		
       treinoDados = new DadosExercicio();
	de.setTreinogeral(treinoGeral);	
	getDados().add(de);
	treinoGeral.setDadosTreino(dados);
Diego_Adriano

Alterei como mencionou, agora deu esso erro:

ST
Hibernate: 
    /* insert br.com.treino.model.TreinoGeral
        */ insert 
        into
            TreinoGeral
            (cliente_id, sessoesrealizadas, sessoesrestantes, sessoestotal) 
        values
            (?, ?, ?, ?)
RP > STG
RP > STD
RP > STD: SUPINO RETO
Hibernate: 
    /* insert br.com.treino.model.DadosExercicio
        */ insert 
        into
            DadosExercicio
            (descanso, exercicio, imprime, peso, repeticao, serie, treinogeral, variacao) 
        values
            (?, ?, ?, ?, ?, ?, ?, ?)
Fev 15, 2012 5:00:40 PM com.sun.faces.lifecycle.InvokeApplicationPhase execute
Advertência: #{treinoBean.salvatreino}: java.lang.IllegalStateException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: br.com.treino.model.DadosExercicio.treinogeral -> br.com.treino.model.TreinoGeral
javax.faces.FacesException: #{treinoBean.salvatreino}: java.lang.IllegalStateException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: br.com.treino.model.DadosExercicio.treinogeral -> br.com.treino.model.TreinoGeral
	at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:118)
	at javax.faces.component.UICommand.broadcast(UICommand.java:315)
	at javax.faces.component.UIViewRoot.broadcastEvents(UIViewRoot.java:794)
	at javax.faces.component.UIViewRoot.processApplication(UIViewRoot.java:1259)
	at com.sun.faces.lifecycle.InvokeApplicationPhase.execute(InvokeApplicationPhase.java:81)
	at com.sun.faces.lifecycle.Phase.doPhase(Phase.java:101)
	at com.sun.faces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:118)
	at javax.faces.webapp.FacesServlet.service(FacesServlet.java:593)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:305)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
	at br.com.treino.filter.ControleFiltro.doFilter(ControleFiltro.java:33)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
	at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
	at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987)
	at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:579)
	at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:309)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
	at java.lang.Thread.run(Thread.java:722)
Caused by: javax.faces.el.EvaluationException: java.lang.IllegalStateException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: br.com.treino.model.DadosExercicio.treinogeral -> br.com.treino.model.TreinoGeral
	at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:102)
	at com.sun.faces.application.ActionListenerImpl.processAction(ActionListenerImpl.java:102)
	... 26 more
Caused by: java.lang.IllegalStateException: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: br.com.treino.model.DadosExercicio.treinogeral -> br.com.treino.model.TreinoGeral
	at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1176)
	at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1112)
	at org.hibernate.ejb.AbstractEntityManagerImpl.convert(AbstractEntityManagerImpl.java:1118)
	at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:738)
	at br.com.treino.repository.TreinoRepository.SalvarTreinoD(TreinoRepository.java:44)
	at br.com.treino.repository.TreinoRepository.SalvarTreinoG(TreinoRepository.java:26)
	at br.com.treino.bean.TreinoBean.salvatreino(TreinoBean.java:92)
	at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	at java.lang.reflect.Method.invoke(Method.java:601)
	at org.apache.el.parser.AstValue.invoke(AstValue.java:262)
	at org.apache.el.MethodExpressionImpl.invoke(MethodExpressionImpl.java:278)
	at com.sun.faces.facelets.el.TagMethodExpression.invoke(TagMethodExpression.java:105)
	at javax.faces.component.MethodBindingMethodExpressionAdapter.invoke(MethodBindingMethodExpressionAdapter.java:88)
	... 27 more
Caused by: org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: br.com.treino.model.DadosExercicio.treinogeral -> br.com.treino.model.TreinoGeral
	at org.hibernate.engine.CascadingAction$9.noCascade(CascadingAction.java:387)
	at org.hibernate.engine.Cascade.cascade(Cascade.java:172)
	at org.hibernate.event.def.AbstractFlushingEventListener.cascadeOnFlush(AbstractFlushingEventListener.java:154)
	at org.hibernate.event.def.AbstractFlushingEventListener.prepareEntityFlushes(AbstractFlushingEventListener.java:145)
	at org.hibernate.event.def.AbstractFlushingEventListener.flushEverythingToExecutions(AbstractFlushingEventListener.java:88)
	at org.hibernate.event.def.DefaultFlushEventListener.onFlush(DefaultFlushEventListener.java:50)
	at org.hibernate.impl.SessionImpl.flush(SessionImpl.java:1206)
	at org.hibernate.ejb.AbstractEntityManagerImpl.flush(AbstractEntityManagerImpl.java:735)
	... 38 more

Fev 15, 2012 5:00:40 PM org.apache.catalina.core.StandardWrapperValve invoke
Grave: Servlet.service() for servlet [Faces Servlet] in context with path [/Treino] threw exception
java.lang.IllegalStateException: Transaction not active
	at org.hibernate.ejb.TransactionImpl.rollback(TransactionImpl.java:104)
	at br.com.treino.filter.ControleFiltro.doFilter(ControleFiltro.java:39)
	at org.apache.catalina.core.ApplicationFilterChain.internalDoFilter(ApplicationFilterChain.java:243)
	at org.apache.catalina.core.ApplicationFilterChain.doFilter(ApplicationFilterChain.java:210)
	at org.apache.catalina.core.StandardWrapperValve.invoke(StandardWrapperValve.java:224)
	at org.apache.catalina.core.StandardContextValve.invoke(StandardContextValve.java:169)
	at org.apache.catalina.authenticator.AuthenticatorBase.invoke(AuthenticatorBase.java:472)
	at org.apache.catalina.core.StandardHostValve.invoke(StandardHostValve.java:168)
	at org.apache.catalina.valves.ErrorReportValve.invoke(ErrorReportValve.java:98)
	at org.apache.catalina.valves.AccessLogValve.invoke(AccessLogValve.java:927)
	at org.apache.catalina.core.StandardEngineValve.invoke(StandardEngineValve.java:118)
	at org.apache.catalina.connector.CoyoteAdapter.service(CoyoteAdapter.java:407)
	at org.apache.coyote.http11.AbstractHttp11Processor.process(AbstractHttp11Processor.java:987)
	at org.apache.coyote.AbstractProtocol$AbstractConnectionHandler.process(AbstractProtocol.java:579)
	at org.apache.tomcat.util.net.JIoEndpoint$SocketProcessor.run(JIoEndpoint.java:309)
	at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1110)
	at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:603)
	at java.lang.Thread.run(Thread.java:722)

Esse parte aqui : [color=red]save the transient instance before flushing: br.com.treino.model.DadosExercicio.treinogeral -> br.com.treino.model.TreinoGeral[/color] Não é pq eu dou em FLUSH() no entityManager antes de chamar o segundo método?

Diego_Adriano

Bão, lendo alguns tópicos aqui do GUJ fiz a seguinte alteração:

@ManyToOne(cascade =CascadeType.ALL)//ADD O CASCADE
@JoinColumn(name="treinogeral")
private TreinoGeral treinogeral;

Após isso, consegui efetuar a inserção, porém com o seguinte detalhe:
Tabela -> Treino Geral
SQL:

id, sessoesrealizadas, sessoesrestantes, sessoestotal, cliente_id
3, 0, 0, 50, 1
4, 0, 0, 50, 1

Tabela -> Dados Exercicio
SQL:

id, descanso, imprime, peso, repeticao, serie, variacao, exercicio, treinogeral
3, 15, b, 10, 12, 3, 1, 1, 4
4, 30, b, 10, 25, 1, 2, 2, 4
5, 10, b, 25, 10, 4, 3, 4, 4

Na tabela Treino Geral foi inserido duas vezes! Porque sera ?

fbl.lucas
Faz o seguinte:
@OneToMany(mappedBy = "treinogeral", cascade = CascadeType.PERSIST)   
private List<DadosExercicio> dadostreino;
E remova a chamada ao método SalvarTreinoD ficando assim:
public void SalvarTreinoG(TreinoGeral tg){  
          
    this.entityManager.persist(tg);  
    this.entityManager.flush();  
          
 //   SalvarTreinoD(tg.getDadosTreino());  
          
}
Tenta primeiro sem a solução que eu dei antes: de.setTreinogeral(treinoGeral); Se der errado tenta com ela.
Diego_Adriano

Lucas, alterei como pediu, porém quando deixo

de.setTreinoGeral(treinoGeral);

Me traz novamente aquele erro, se eu deixar sem ele o Obj é persistido, tanto em Geral quanto em Dados, porém o Relacionamento não é salvo …

fbl.lucas
Volta para seu codigo inicial e deixa o metodo SalvarTreinoD como abaixo:
public void SalvarTreinoD(TreinoGeral tg,List<DadosExercicio> dados){  
  
  
    for (DadosExercicio td : dados){  
        td.setTreinoGeral(tg);  
        if (td.getVariacao() == 1){  
            td.setImprime(true);  
              
        }else{  
            td.setImprime(false);  
        }  
              
    this.entityManager.persist(td);  
    this.entityManager.flush();  
              
     }  
          
}
Diego_Adriano

Caraca Lucas, agora funfou …
Ficou como vc mesmo sugeriu …
Obrigado pela força, vou alterar o tópico aqui pra resolvido …
Abraços

Criado 14 de fevereiro de 2012
Ultima resposta 15 de fev. de 2012
Respostas 14
Participantes 3