ManyToMany - Correto usar? Dificuldade

6 respostas
kaahxd

Boa tarde!!

Bem tenho uma aplicação e preciso fazer um cadastro no banco de dados no seguinte estilo:

tenho varios códigos cadastrados, esses códigos servem para especificar o que cada unidade faz, posso cadastrar várias unidades também. Ao cadastrar uma unidade necessitaria selecionar os códigos com suas funções, uma unidade pode exercer mais de uma função e portanto possuir mais de um código, esse código pode ser usado por várias unidades. Pensei em criar uma lista de check box [interface web] e o usuario poder selecionar.

Imaginei então o relacionamento é n para n, vou usar @ManyToMany, porém pensei, Se o usuario selecionar 3 campos, como isso ficará no banco de dados? a coluna código vai possuir 3 valores diferentes? Bem mesmo assim resolvi tentar e implementei da seguinte forma:

//imports omitidos 

@Entity
@Table(name = "unidades")
public class Unidade {
	@Id
	@GeneratedValue
	private Integer id;

       // Outros Atributos

	@ManyToMany
	private Cnai cnai;

	// Getters e Setters

	public void setCnai(Cnai cnai) {
		this.cnai = cnai;
	}

}

Cnai seria o nome do código que determina a função da unidade. Isso não funcionou, segue o erro que diz que estou fazendo uma tentativa Ilegal do ManyToMany:

description The server encountered an internal error () that prevented it from fulfilling this request.

exception

org.springframework.web.util.NestedServletException: Handler processing failed; nested exception is java.lang.ExceptionInInitializerError
	org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:839)
	org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
	org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:669)
	org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:585)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:722)

root cause

java.lang.ExceptionInInitializerError
	br.com.e2s.dao.UsuarioDAO.<init>(UsuarioDAO.java:25)
	br.com.e2s.controller.AcessoController.efetuaLogin(AcessoController.java:64)
	sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	java.lang.reflect.Method.invoke(Method.java:616)
	org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176)
	org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:436)
	org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:424)
	org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790)
	org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
	org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:669)
	org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:585)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:722)

root cause

javax.persistence.PersistenceException: [PersistenceUnit: e2s] Unable to configure EntityManagerFactory
	org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:371)
	org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:55)
	javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:48)
	javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:32)
	br.com.e2s.infra.JPAUtil.<clinit>(JPAUtil.java:9)
	br.com.e2s.dao.UsuarioDAO.<init>(UsuarioDAO.java:25)
	br.com.e2s.controller.AcessoController.efetuaLogin(AcessoController.java:64)
	sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	java.lang.reflect.Method.invoke(Method.java:616)
	org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176)
	org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:436)
	org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:424)
	org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790)
	org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
	org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:669)
	org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:585)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:722)

root cause

org.hibernate.AnnotationException: Illegal attempt to map a non collection as a @OneToMany, @ManyToMany or @CollectionOfElements: br.com.e2s.modelo.Unidade.cnai
	org.hibernate.cfg.annotations.CollectionBinder.getCollectionBinder(CollectionBinder.java:316)
	org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:1642)
	org.hibernate.cfg.AnnotationBinder.processIdPropertiesIfNotAlready(AnnotationBinder.java:762)
	org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:726)
	org.hibernate.cfg.AnnotationConfiguration.processArtifactsOfType(AnnotationConfiguration.java:636)
	org.hibernate.cfg.AnnotationConfiguration.secondPassCompile(AnnotationConfiguration.java:359)
	org.hibernate.cfg.Configuration.buildMappings(Configuration.java:1206)
	org.hibernate.ejb.Ejb3Configuration.buildMappings(Ejb3Configuration.java:1449)
	org.hibernate.ejb.EventListenerConfigurator.configure(EventListenerConfigurator.java:193)
	org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:1077)
	org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:275)
	org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:359)
	org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:55)
	javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:48)
	javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:32)
	br.com.e2s.infra.JPAUtil.<clinit>(JPAUtil.java:9)
	br.com.e2s.dao.UsuarioDAO.<init>(UsuarioDAO.java:25)
	br.com.e2s.controller.AcessoController.efetuaLogin(AcessoController.java:64)
	sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
	sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
	sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
	java.lang.reflect.Method.invoke(Method.java:616)
	org.springframework.web.bind.annotation.support.HandlerMethodInvoker.invokeHandlerMethod(HandlerMethodInvoker.java:176)
	org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.invokeHandlerMethod(AnnotationMethodHandlerAdapter.java:436)
	org.springframework.web.servlet.mvc.annotation.AnnotationMethodHandlerAdapter.handle(AnnotationMethodHandlerAdapter.java:424)
	org.springframework.web.servlet.DispatcherServlet.doDispatch(DispatcherServlet.java:790)
	org.springframework.web.servlet.DispatcherServlet.doService(DispatcherServlet.java:719)
	org.springframework.web.servlet.FrameworkServlet.processRequest(FrameworkServlet.java:669)
	org.springframework.web.servlet.FrameworkServlet.doPost(FrameworkServlet.java:585)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:641)
	javax.servlet.http.HttpServlet.service(HttpServlet.java:722)

Se alguém puder me ajudar, Muito Obrigado!

6 Respostas

rodrigo.bossini

Essa sua varíavel do tipo Cnai precisa ser uma coleção. Um Set ou List de Cnai.

kaahxd

Pode me dar um exemplo de como usar?

Y

Many to Many é, obviamente, muitos para muitos.

O que significa que um usuario pode ter muitos cnais e um cnai pode ter muitos usuarios.

Entao voce tem que mapear uma coleção:

private List<Cnais> cnaisDoUsuario;
kaahxd

Obrigado pela ajuda! Funcionou, consegui executar a aplicação sem gerar erros e foi criada uma tabela no banco de dados chamada unidades_cnai.

Bem o problema está no cadastro agora, eu cadastro tudo como fazia anteriormente, porém os códigos não são relacionados na tabela unidades_cnai e não aparecem em nenhum outro lugar, como se eu não tivesse os selecionados e registrado.

Código da front através da qual é feito o registro:

<td> 
<select size="4" multiple="multiple" name="cnai.id">
<c:forEach var="cnai" items="${dao.lista}">
<option value="${cnai.id}">${cnai.codigo}</option>
</c:forEach>
</select>
</td>

Método que faz a gravação no banco:

@RequestMapping("adicionaUnidade")
	public String adicionaUnidade(@Valid Unidade unidade, BindingResult result,
			Model model) {

		EntityManager em = new JPAUtil().getEntityManager();
		UnidadeDAO dao = new UnidadeDAO(em);
		em.getTransaction().begin();

                //Regras de validação

		dao.getAdiciona(unidade);
		em.getTransaction().commit();
		em.close();

		return "redirect:cadastroUnidade";
	}

E como ficou minha classe modelo:

//Imports omitidos
public class Unidade {
	//Outros atributos

	@ManyToMany
	private List<Cnai> cnai;

	// Geters e Setters

	public List<Cnai> getCnai() {
		EntityManager em = new JPAUtil().getEntityManager();
		CnaiDAO dao = new CnaiDAO(em);

		return dao.getLista();
	}

	public void setCnai(List<Cnai> cnai) {
		this.cnai = cnai;
	}

}
Y

kaahxd:
Obrigado pela ajuda! Funcionou, consegui executar a aplicação sem gerar erros e foi criada uma tabela no banco de dados chamada unidades_cnai.

Bem o problema está no cadastro agora, eu cadastro tudo como fazia anteriormente, porém os códigos não são relacionados na tabela unidades_cnai e não aparecem em nenhum outro lugar, como se eu não tivesse os selecionados e registrado.

Voce tem uma tabela unidade, uma tabela cnai e uma tabela unidade_cnai? Se sim, garanta que os cnais existem em sua tabela.

Se voce so tem unidade e unidades_cnai o mapeamento esta errado, deveria ser oneToMany.

Veja tambem se voce esta usando os cascade de acordo.

Qualquer coisa da uma olhada na documentacao dessa parte:
http://docs.jboss.org/hibernate/orm/4.1/manual/en-US/html/ch08.html

kaahxd

YvGa:
kaahxd:
Obrigado pela ajuda! Funcionou, consegui executar a aplicação sem gerar erros e foi criada uma tabela no banco de dados chamada unidades_cnai.

Bem o problema está no cadastro agora, eu cadastro tudo como fazia anteriormente, porém os códigos não são relacionados na tabela unidades_cnai e não aparecem em nenhum outro lugar, como se eu não tivesse os selecionados e registrado.

Voce tem uma tabela unidade, uma tabela cnai e uma tabela unidade_cnai? Se sim, garanta que os cnais existem em sua tabela.

Se voce so tem unidade e unidades_cnai o mapeamento esta errado, deveria ser oneToMany.

Veja tambem se voce esta usando os cascade de acordo.

Qualquer coisa da uma olhada na documentacao dessa parte:
http://docs.jboss.org/hibernate/orm/4.1/manual/en-US/html/ch08.html

Sim possuo uma tabela cnai, uma tabela unidades e uma tabela unidades_cnai. Como mostrei no post anterior, uutilo um forEach para criar uma lista com todos os Cnais registrados, não to conseguindo saber e consequentemente corrigir, o motivo de ao clicar para gravar, não é salvo os cnais selecionados na tabela unidades_cnai.

Criado 22 de outubro de 2012
Ultima resposta 23 de out. de 2012
Respostas 6
Participantes 3