Mapeamento Muitos para Muitos em Hibernate com JPA

Mapeamento Muitos para Muitos em Hibernate com JPA

O exemplo abaixo descreve o mapeamento N para M no hibernate. Ao mapear o muitos-para-muitos , o hibernate automaticamente cria um terceira tabela denominada tabela de ligação entre elas. Essa tabela de ligação é composta pela chave primaria dela e uma chave estrangeira referente a cada tabela.
A lista das bibliotecas (arquivos .jar) do Oracle, Hibernate e Servlet 3.0 necessários são:

As libs do Projeto são : JSF 2.0 , Primefaces 4.0 , Oracle necessárias são:

antlr-2.7.6.jar commons-fileupload-1.0.jar jakarta-oro.jar
asm-attrs.jar commons-lang-2.1.jar javaee.jar
asm.jar commons-logging-1.1.1.jar jstl-1.1.0.jar
c3p0-0.9.0.jar commons-validator.jar jstl.jar
cglib-2.1.3.jar dom4j-1.6.1.jar jta.jar
commons-beanutils-1.8.0.jar ejb3-persistence.jar log4j-1.2.15.jar
commons-codec-1.3.jar hibernate-annotations.jar ojdbc14.jar
commons-collections-3.2.1.jar hibernate-commons-annotations.jar oro-2.0.8.jar
commons-digester-2.0.jar hibernate3.jar servlet-api.jar
commons-el-1.0.jar hsqldb.jar standard.jar

Arquivos de Configuração do Hibernate

oracle_hibernate_cfg.xml

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE hibernate-configuration PUBLIC "-//Hibernate/Hibernate Configuration DTD 3.0//EN" "http://hibernate.sourceforge.net/hibernate-configuration-3.0.dtd">
<hibernate-configuration>
  <session-factory>
  
    <property name="hibernate.dialect">org.hibernate.dialect.OracleDialect</property>
    <property name="hibernate.connection.driver_class">oracle.jdbc.OracleDriver</property>
    <property name="hibernate.connection.url">jdbc:oracle:thin:@127.0.0.1:1521:XE</property>
    <!-- Usuario do banco de dados, exemplo system -->
    <property name="hibernate.connection.username">usuario</property>

    <!-- Senha do Usuario do banco de dados  -->    
    <property name="hibernate.connection.password">senha</property>
    
    <!-- Mostra todo o codigo sql no console -->
    <property name="hibernate.show_sql">true</property>
    
    <!-- Mostra o sql formatado no console -->
    <property name="hibernate.format_sql">true</property>
    
    <!-- Classes da Aplicação Mapeadas -->
    <mapping class="entity.Venda"/>
    <mapping class="entity.Produto"/>
    
  </session-factory>
</hibernate-configuration>    

HibernateUtil.java

package persistence;

import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.SessionFactory;

// Função para abrir a conexao com o banco de dados
public class HibernateUtil {
    private static final SessionFactory sessionFactory;

    static {
        try {
            
            sessionFactory = new AnnotationConfiguration().
            		configure("config/oracle_hibernate.cfg.xml").buildSessionFactory();
        } catch (Throwable ex) {
            
            System.err.println("Initial SessionFactory creation failed." + ex);
            throw new ExceptionInInitializerError(ex);
        }
    }

    public static SessionFactory getSessionFactory() {
        return sessionFactory;
    }
}    

Classes mapeadas no Hibernate com relacionamento muitos para muitos.

package entity;

import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToMany;
import javax.persistence.SequenceGenerator;

@Entity
@SequenceGenerator(name="seqMedico",sequenceName="seqMedico")
public class Medico {
	
	@Id
	@GeneratedValue(generator="seqMedico")	
	private Integer idMedico;
	
	@Column(length=35)
	private String nomeMedico;
	
	@ManyToMany(mappedBy="medicos")
	private List pacientes;
	
	public Medico() {
		// TODO Auto-generated constructor stub
	}

	public Medico(Integer idMedico, String nomeMedico) {
		super();
		this.idMedico = idMedico;
		this.nomeMedico = nomeMedico;
	}

	@Override
	public String toString() {
		return "Medico [idMedico=" + idMedico + ", nomeMedico=" + nomeMedico
				+ "]";
	}

	public Integer getIdMedico() {
		return idMedico;
	}
	public void setIdMedico(Integer idMedico) {
		this.idMedico = idMedico;
	}
	public String getNomeMedico() {
		return nomeMedico;
	}
	public void setNomeMedico(String nomeMedico) {
		this.nomeMedico = nomeMedico;
	}
	public List getPacientes() {
		return pacientes;
	}
	public void setPacientes(List pacientes) {
		this.pacientes = pacientes;
	}
}    
package entity;

import java.util.List;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.SequenceGenerator;

@Entity
@SequenceGenerator(sequenceName="seqPaciente", name="seqPaciente")
public class Paciente {
	
	@Id
	@GeneratedValue(generator="seqPaciente")
	private Integer idPaciente;
	
	@Column(length=50)
	private String nomePaciente;
	
	@ManyToMany
	@JoinTable(name="MedicoPaciente", 
			   joinColumns=@JoinColumn(name="id_Medico"),
			   inverseJoinColumns=@JoinColumn(name="id_Paciente")
			   )
	private List medicos;
	
	public Paciente() {
		// TODO Auto-generated constructor stub
	}

	public Paciente(Integer idPaciente, String nomePaciente) {
		super();
		this.idPaciente = idPaciente;
		this.nomePaciente = nomePaciente;
	}

	@Override
	public String toString() {
		return "Paciente [idPaciente=" + idPaciente + ", nomePaciente="
				+ nomePaciente + "]";
	}

	public Integer getIdPaciente() {
		return idPaciente;
	}
	public void setIdPaciente(Integer idPaciente) {
		this.idPaciente = idPaciente;
	}
	public String getNomePaciente() {
		return nomePaciente;
	}
	public void setNomePaciente(String nomePaciente) {
		this.nomePaciente = nomePaciente;
	}
	public List getMedicos() {
		return medicos;
	}
	public void setMedicos(List medicos) {
		this.medicos = medicos;
	}
}    

Classe para executar automaticamente o script do banco de dados baseado no mapeamento feito nas classes.

package config;

import org.hibernate.cfg.AnnotationConfiguration;
import org.hibernate.cfg.Configuration;
import org.hibernate.tool.hbm2ddl.SchemaExport;

// Classe para gerar o banco de dados apartir do mapeamento das classe no oracle_hibernate.cfg.xml

public class Main {
	
	public static void main(String[] args) {		
		Configuration cfg = new AnnotationConfiguration().configure("config/oracle_hibernate.cfg.xml");
		new SchemaExport(cfg).create(true, true);		
	}
}    

Classes que possuem os métodos referentes ao CRUD.

package persistence;

import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;

import entity.Medico;

public class MedicoDao {
	
	Session session;
	Transaction transaction;
	Criteria criteria;
	Query query;
	
	
	public void create(Medico m) throws Exception{		
		session = HibernateUtil.getSessionFactory().openSession();
			transaction = session.beginTransaction();
				session.save(m);
			transaction.commit();
		session.close();		
	}

	public void delete(Medico m) throws Exception{		
		session = HibernateUtil.getSessionFactory().openSession();
			transaction = session.beginTransaction();
				session.delete(m);
			transaction.commit();
		session.close();		
	}
	
	public void update(Medico m) throws Exception{		
		session = HibernateUtil.getSessionFactory().openSession();
			transaction = session.beginTransaction();
				session.update(m);
			transaction.commit();
		session.close();		
	}
	
	public List findAll(){		
		session = HibernateUtil.getSessionFactory().openSession();
			List lista = session.createQuery("from Medico").list();
		session.close();
		return lista;
	}
	
	public Medico findByCod(Integer cod){		
		session = HibernateUtil.getSessionFactory().openSession();
		Medico medico = (Medico) session.get(Medico.class, cod);
		session.close();
		return medico;
	}
}    
package persistence;

import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.Query;
import org.hibernate.Session;
import org.hibernate.Transaction;

import entity.Paciente;

public class PacienteDao {

	Session session;
	Transaction transaction;
	Criteria criteria;
	Query query;
	
	public void create(Paciente p) throws Exception{		
		session = HibernateUtil.getSessionFactory().openSession();
			transaction = session.beginTransaction();
				session.save(p);
			transaction.commit();
		session.close();		
	}

	public void create(Paciente p , List medicos){
		
		session = HibernateUtil.getSessionFactory().openSession();
			transaction = session.beginTransaction();				
				session.save(p);
				p.setMedicos(medicos);				
				for(Medico m : medicos){
					session.save(m);
				}				
			transaction.commit();
		session.close();
		
	}
	
	public void delete(Paciente p) throws Exception{		
		session = HibernateUtil.getSessionFactory().openSession();
			transaction = session.beginTransaction();
				session.delete(p);
			transaction.commit();
		session.close();		
	}
	
	public void update(Paciente p) throws Exception{		
		session = HibernateUtil.getSessionFactory().openSession();
			transaction = session.beginTransaction();
				session.update(p);
			transaction.commit();
		session.close();		
	}
	
	public List findAll(){		
		session = HibernateUtil.getSessionFactory().openSession();
			List lista = session.createQuery("from Paciente").list();
		session.close();
		return lista;
	}
	
	public Paciente findByCod(Integer cod){		
		session = HibernateUtil.getSessionFactory().openSession();
		Paciente paciente = (Paciente) session.get(Paciente.class, cod);
		session.close();
		return paciente;
	}
}    

Executando no método main

package main;

import java.util.ArrayList;
import java.util.List;

import persistence.MedicoDao;
import persistence.PacienteDao;
import entity.Medico;
import entity.Paciente;

public class Main {

	public static void main(String[] args) {
				
		Medico m1 = new Medico(null, "Joao");
		Medico m2 = new Medico(null, "Pedro");
				
		Paciente p1 = new Paciente(null, "Miguel");
		Paciente p2 = new Paciente(null, "Sergio");
		
		Paciente p3 = new Paciente(null, "Antonio");
		
		List listaM = new ArrayList<>();
		listaM.add(m1);listaM.add(m2);
		List listaP = new ArrayList<>();
		listaP.add(p1); listaP.add(p2);
		
		try {
			
			//Cadastrar os Medicos			
			for(Medico m : listaM){
				new MedicoDao().create(m);
			}
			
			//Relacionar o Primeiro Medico com a Lista de Paciente			
			Medico medico = new MedicoDao().findByCod(1);
			
			for(Paciente p : listaP){
				p.setMedicos(new ArrayList());
				p.getMedicos().add(medico);
				new PacienteDao().create(p);
			}
			
			Medico medico1 = new MedicoDao().findByCod(2);
			
			for(Paciente p : listaP){
				p.setMedicos(new ArrayList());
				p.getMedicos().add(medico1);
				new PacienteDao().create(p);
			}
			
			
			//Cadastrar um Paciente para varios medicos			
			new PacienteDao().create(p3, listaM);
			
			//Imprime Medico e a sua lista de Pacientes			
			for(Medico m : new MedicoDao().findAll()){
				System.out.println("Medico:" + m);
				
				for(Paciente p : m.getPacientes()){
					System.out.println("Paciente" + p);
				}
			}			
		} catch (Exception ex) {
			System.out.println("Error " + ex.getMessage());
		}
	}
}