[Resolvido] Hibernate ManyToMany

6 respostas
P

Saudações,
estou com problemas para mapear um relacionamento,

obtenhos de 3 tabelas, Profissional, Empresa, Empresa-Prof
sendo a tabela Empresa-Prof o relacionamento entre empresa e profissional.

Profissional
 :arrow: num-profissional
Empresa
 :arrow: cnpj
Empresa-Prof
 :arrow: cnpj
 :arrow: num-profissional
 :arrow: cargo

A principio o mapeamento esta assim nos DTOs,
:arrow: ProfissionalDTO

@Table(name="profissional")
public class ProfissionalDTO implements Serializable {

    @ManyToMany(
        targetEntity=EmpresaDTO.class,
        cascade={javax.persistence.CascadeType.ALL}
    )
    @JoinTable(
        name="empresa-prof",
        joinColumns={@JoinColumn(name="num-profissional")},
        inverseJoinColumns={@JoinColumn(name="cnpj")}
    )
	private Set<EmpresaDTO> empresas;

:arrow: EmpresaDTO

@Entity
@Table(name="empresa")
public class EmpresaDTO  implements Serializable {

    @ManyToMany(
        targetEntity=ProfissionalDTO.class,
        cascade={CascadeType.ALL}
    )
    @JoinTable(
        name="empresa-prof",
        joinColumns={@JoinColumn(name="cnpj")},
        inverseJoinColumns={@JoinColumn(name="num-profissional")}
    )
	private Set<ProfissionalDTO> profissionais;

um dos erros que estou recebendo é que quando faço um select no hql buscando o profissional pela chave, fazendo left join com empresas, ele me traz um Object[2], sendo Object[0] o profissionalDTO, e o Object[1] null… nao sei pq disso…

outra coisa que ta quebrando e que tem o campo cargo na tabela de relacionamento, e a mesma nao possuo chave primaria. sendo assim eu acho que nao conseguiria fazer um DTO para essa tabela de relacionamento, pq o hibernate exige um id…

alguma sugestão?

6 Respostas

D

Amigo,

acredito que o seu problema está na forma com que você criou a tabela de ligação, o hibernate não faz bem ligações ternárias. Tente fazer uma tabela de ligação sem o campo cargo.

fw

P

Dieval Guizelini:
Amigo,

acredito que o seu problema está na forma com que você criou a tabela de ligação, o hibernate não faz bem ligações ternárias. Tente fazer uma tabela de ligação sem o campo cargo.

fw

Obrigado por postar,

na verdade essa tabela ja existe no sistema ativo, nao foi eu quem criou, mas caso eu consiga remover o campo cargo, o que poderia estar causando o retorno errônico do q.uniqueResult trazer um vertor ao inves do objeto em si?

U

ola, não sei se meu código sera util para você mas mesmo assim fiz ele para estudo, aqui vai os codigos(utilizando xml).

Empresa.java

public class Empresa {
	private Long cnpj;
	private String razaoSocial;
	private Set profissionais = new HashSet();
}

Profissional.java

public class Profissional {
	private Long id;
	private String nome;
	private Set empresas = new HashSet();
}

mapeamentos:

Empresa.hbm.xml

&lt?xml version="1.0"?&gt
&lt;!DOCTYPE hibernate-mapping PUBLIC
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"&gt;
&lt;hibernate-mapping&gt;
	&lt;class name="guj.Empresa" table="EMPRESA"&gt;
		&lt;id name="cnpj"&gt;
			&lt;generator class="native"&gt;&lt;/generator&gt;
		&lt;/id&gt;
		&lt;property name="razaoSocial" length="50" /&gt;

		&lt;set name="profissionais" table="EMPRESA_PROF" cascade="all" &gt;
			&lt;key column="cnpj"&gt;&lt;/key&gt;
			&lt;many-to-many column="PROFISSIONAL_ID" class="guj.Profissional" /&gt;
		&lt;/set&gt;
	&lt;/class&gt;
&lt;/hibernate-mapping&gt;

Profissional.hbm.xml

&lt?xml version="1.0"?&gt
&lt;!DOCTYPE hibernate-mapping PUBLIC
	"-//Hibernate/Hibernate Mapping DTD 3.0//EN"
	"http://hibernate.sourceforge.net/hibernate-mapping-3.0.dtd"&gt;
&lt;hibernate-mapping&gt;
	&lt;class name="guj.Profissional"&gt;
		&lt;id name="id" column="PROFISSIONAL_ID"&gt;
			&lt;generator class="native" /&gt;
		&lt;/id&gt;
		&lt;property name="nome" /&gt;
		&lt;set name="empresas" table="EMPRESA_PROF" cascade="all" &gt;
			&lt;key column="PROFISSIONAL_ID" /&gt;
			&lt;many-to-many column="CNPJ" class="guj.Empresa" /&gt;
		&lt;/set&gt;
	&lt;/class&gt;
&lt;/hibernate-mapping&gt;

EmpresaManager:

package guj;

import org.hibernate.Session;

public class EmpresaManager {
	
	public static void main(String args[]) {
		
		EmpresaManager em = new EmpresaManager();
		
		//em.saveSimpleEmpresaAndProf();
		//em.saveEmpresaProf();
		em.saveProfEmpresa();
		
		HibernateUtil.shutdown();
	}
	/**
	 * Este metodo o relacionamento(direção) é PROFISSIONAL -&gt EMPRESA.
	 */	
	private void saveProfEmpresa() {
		
		Profissional prof = new Profissional();
		prof.setNome("Alex");
		
		Empresa emp1 = new Empresa();
		Empresa emp2 = new Empresa();
		
		prof.getEmpresas().add(emp1);
		prof.getEmpresas().add(emp2);
		
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		
		session.beginTransaction();
		
		session.save(prof);
		
		session.getTransaction().commit();
		
		//Nova transação, Só para exemplo!
		session = HibernateUtil.getSessionFactory().getCurrentSession();
		session.beginTransaction();
		
		Profissional prof2 = (Profissional) session.load(Profissional.class, prof.getId());
		
		System.out.println("Profissional: "+prof2.getNome()+ " - "+prof2.getEmpresas().size());
		
		session.getTransaction().commit();				
		
	}
	/**
	 * Este metodo o relacionamento(direção) é EMPRESA -&gt PROFISSIONAL.
	 */
	private void saveEmpresaProf() {
		
		Empresa empresa = new Empresa();
		
		empresa.setRazaoSocial("Alex's company");
		
		Profissional p1 = new Profissional();
		Profissional p2 = new Profissional();
		
		p1.setNome("Alex");
		p2.setNome("Alex2");
				
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		
		session.beginTransaction();
		
		empresa.getProfissionais().add(p1);
		empresa.getProfissionais().add(p2);
		
		session.save(empresa);
		
		session.getTransaction().commit();
		
		//Nova transação, Só para exemplo!
		
		session = HibernateUtil.getSessionFactory().getCurrentSession();
		
		session.beginTransaction();
		
		Empresa empresa2 = (Empresa) session.load(Empresa.class, empresa.getCnpj());
		
		System.out.println("Empresa:"+empresa2.getRazaoSocial()+" - "+empresa2.getProfissionais().size());
		
		session.getTransaction().commit();							
		
	}

	private void saveSimpleEmpresaAndProf() {
		
		Empresa empresa = new Empresa();
		Profissional prof = new Profissional();
		
		Session session = HibernateUtil.getSessionFactory().getCurrentSession();
		
		session.beginTransaction();
		
		session.save(empresa);
		session.save(prof);
		
		session.getTransaction().commit();
				
	}
	
}

bom basicamente nesse esquema deveria ser possivel trabalhar com o relacionamento (EMPRESA -&gt PROFISSIONAL e PROFISSIONAL -&gt EMPRESA) sem maiores problemas.

quiser baixer todo o código basta fazer download:

http://www.alexflorentino.com/codes/exemplo.zip

qualquer comentario será bem vindo.

P

ualex,
obrigado pelo empenho de fazer todo o código,
E meus parabéns por tornar o meu problema um objeto de estudo, isso mostra o quanto você gosta do que faz, e nao mede esforço para ajudar os outros… em um ambiente de trabalho isso é essencial.

o seu código foi muito util pra mim,
Eu vou estar testando certinho as possibilidades, e verificar se será possível remover o campo cargo dakela dabela de relacionamento, caso contrario acredito que a unica coisa que poderia ser feita é criar um identificador pra ela, e tornar ela um objeto e fazer o ManyToOne nela.

mais uma vez obrigado, e parabéns pela iniciativa!

nom mais, quando concluido postarei aqui o codigo com a respectiva resolução :slight_smile:

U

eu não entendo a dificuldade com o Cargo… isso é campo texto ou é um codigo para (FK) ? se for uma fk vc precisa “só” criar um novo objeto e novo mapeamento ou se for uma string só criar uma nova propriedade.

P

o grande problema que eu tinha era que as tabelas e colunas tem como nome, um separador “-” hifen, e ao traduzí-lo pra sql o hibernate nao colocava aspas, ai o jdbc nao encontrava a tabela…

faltou um fetch no left join ¬¬ por isso vinha um vetor ao inves do objeto.


Problemas resolvidos.

criado objeto EmpresaProfissionalDTO para efetuar o relacionamento, nao removendo a coluna cargo.

@Entity
@Table(name="\"sim-empresa-prof\"", schema="PUB")
public class EmpresaProfissionalDTO implements Serializable {
 	@ManyToOne(fetch = FetchType.EAGER, targetEntity = ProfissionalDTO.class)
 	@JoinColumn(name="\"num-profissional\"", insertable = false, updatable = false)
 	private ProfissionalDTO profissional;
 
 	@ManyToOne(fetch = FetchType.EAGER, targetEntity = EmpresaDTO.class)
 	@JoinColumn(name="cnpj", insertable = false, updatable = false)
 	private EmpresaDTO empresa;

e pra resolver o problema das aspas, bastou fazer o seguinte no ProfissionalDTO,
@JoinColumn(name="“num-profissional”")

@OneToMany(targetEntity = EmpresaProfissionalDTO.class ,mappedBy="profissional", cascade= javax.persistence.CascadeType.ALL)
	@JoinColumn(name="\"num-profissional\"")
 	@Cascade(value = CascadeType.DELETE_ORPHAN)
 	@Fetch(FetchMode.JOIN)
 	private Set<EmpresaProfissionalDTO> empresaProfissional;

Problemas Resolvidos, obrigado pela ajuda :slight_smile:

Criado 17 de agosto de 2007
Ultima resposta 20 de ago. de 2007
Respostas 6
Participantes 3