Relacionamentos Hibernate (Many-to-Many)

16 respostas
B

Bom dia pessoal,
Sei que já existem vários topicos em relação a isso, e podem apostar que já li a maioria…:S

Seguinte tenho o seguinte cenário:

Ticket.java

@Entity
@Table(name="ticket")
public class Ticket implements Serializable {

	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	private Integer id;
	
	private Integer ticketNumero;
	
	private Status status;
	
	@OneToOne(cascade={CascadeType.ALL})
	private TicketTime ticketTime;

	@ManyToMany(cascade={CascadeType.ALL}, targetEntity=br.hourmanagement.model.Projeto.class)
	@JoinTable(name="projeto_has_ticket",
			   joinColumns=@JoinColumn(name="ticket_id"),
			   inverseJoinColumns=@JoinColumn(name="projeto_id"))
	private Collection<Projeto> projetos;

Projeto.java

@Entity
@Table(name="projeto")
public class Projeto implements Serializable {
	
	@Id
	@GeneratedValue(strategy=GenerationType.AUTO)
	private Integer id;
	
	private String nome;

	@ManyToMany(cascade={CascadeType.ALL}, targetEntity=br.hourmanagement.model.Ticket.class, mappedBy="projetos")
	@JoinTable(name="projeto_has_ticket",
			   joinColumns=@JoinColumn(name="projeto_id"),
			   inverseJoinColumns=@JoinColumn(name="ticket_id"))
	private Collection<Ticket> tickets;

Main.java

public static void main(String[] args) {
		Ticket ticket = new Ticket();
		
		TicketTime ticketTime = new TicketTime();
		ticketTime.setDataFim(new Timestamp(2009, 04, 27, 6, 55, 00, 00));
		ticketTime.setDataInicio((new Timestamp(2009, 04, 27, 5, 55, 00, 00)));
		
		ticket.setTicketTime(ticketTime);
		
		ticket.setTicketNumero(4101);
		ticket.setStatus(Status.STOP);
		
		Collection<Ticket> tickets = new LinkedList<Ticket>();
		tickets.add(ticket);
		
		Projeto projeto = new Projeto();
		projeto.setNome("Teste2");
		projeto.setTickets(tickets);
		
		DaoFactory daoFactory = new DaoFactory();
		Dao dao = daoFactory.getProjetoDao();
		
		dao.adiciona(projeto);
}

Relacionamento:

projeto -> projeto_has_ticket <- ticket

O problema é que ele insere nas tabelas projeto e ticket, mais não insere na de relacionamento.
Já tentei seguir o exemplo da própria documentação do Hibernate, porém não funciona…

Não sei mais oq fazer, agluém pode me ajudar?

vlw

16 Respostas

T

tenta fazer

Collection<Projeto> projetos = new LinkedList<Projeto>();  
projetos.add(projeto);  

ticket.setProjetos(projetos);
B

Não gravou. Ele insere em todas menos na de relacionamento.

Uma observação estou usando os imports do javax.persistence.*

T
@ManyToMany(cascade={CascadeType.ALL}, targetEntity=br.hourmanagement.model.Projeto.class, mappedBy="tickets")  
@JoinTable(name="projeto_has_ticket", joinColumns=@JoinColumn(name="ticket_id"),  inverseJoinColumns=@JoinColumn(name="projeto_id"))  
private Collection<Projeto> projetos;
B

Então…não funco…

Continuo adicionado a collection de Projetos em Tickets e Tickets em Projetos.

T

quando eu precisei fazer relacionamento ManyToMany entre 2 objetos, eu não coloquei os Joins declarados, o próprio Hibernate se encarregou de fazer isso…porque o certo é ele fazer as tabelas de relacionamentos e não criar campos…

B

Então, deixa eu entender…vc não criou a tabela de relacionamento no banco?

T

Quando eu trabalho com Hibernate e mapeamento de classes eu evito pensar em tabelas relacionadas, isso porque é um pouco diferente pensar objetos dentro de objetos. no banco eu nao crio nada, somente as classes e seus relacionamentos (por exemplo: projetos possui tickets)…tente fazer isso:

@Entity  
 @Table(name="ticket")  
 public class Ticket implements Serializable {  
   
     @Id  
     @GeneratedValue(strategy=GenerationType.AUTO)  
     private Integer id;  
       
     private Integer ticketNumero;  
       
     private Status status;  
       
     @OneToOne(cascade={CascadeType.ALL})  
     private TicketTime ticketTime;  
   
     @ManyToMany(cascade={CascadeType.ALL})  
     private List<Projeto> projetos; 
}

 @Entity  
 @Table(name="projeto")  
 public class Projeto implements Serializable {  
       
     @Id  
     @GeneratedValue(strategy=GenerationType.AUTO)  
     private Integer id;  
       
     private String nome;  
   
     @ManyToMany(cascade={CascadeType.ALL}, mappedBy="projetos")  
     private List<Ticket> tickets;  
}



    public static void main(String[] args) {  
            Ticket ticket = new Ticket();  
              
            TicketTime ticketTime = new TicketTime();  
            ticketTime.setDataFim(new Timestamp(2009, 04, 27, 6, 55, 00, 00));  
            ticketTime.setDataInicio((new Timestamp(2009, 04, 27, 5, 55, 00, 00)));  
              
            ticket.setTicketTime(ticketTime);  
              
           ticket.setTicketNumero(4101);  
           ticket.setStatus(Status.STOP);  
             
           List<Ticket> tickets = new LinkedList<Ticket>();  
           tickets.add(ticket);  
             
           Projeto projeto = new Projeto();  
           projeto.setNome("Teste2");  
           projeto.setTickets(tickets);  

           List<Projeto> projetos = new LinkedList<Projeto>();
           projetos.add(projeto);

           tickets.setProjetos(projetos);             

           DaoFactory daoFactory = new DaoFactory();  
           Dao dao = daoFactory.getProjetoDao();  
             
           dao.adiciona(projeto);  
   }

creio que esse código funcione, não fiz um projeto para testar, se não funcionar eu faço um projeto rápido aki para testar…

B

Mesmo assim não funco…parece que ele não está sabendo que tem que inserir na tabela de relacionamento.

T

Fiz esse projeto e funcionou…

@Entity
@Table(name = "projeto")
public class Projeto implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;
    private String nome;
    @ManyToMany(cascade = {CascadeType.ALL}, mappedBy = "projetos")
    private List<Ticket> tickets;

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public String getNome() {
        return nome;
    }

    public void setNome(String nome) {
        this.nome = nome;
    }

    public List<Ticket> getTickets() {
        return tickets;
    }

    public void setTickets(List<Ticket> tickets) {
        this.tickets = tickets;
    }
}  


@Entity
@Table(name = "ticket")
public class Ticket implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Integer id;
    private Integer ticketNumero;
    
    @ManyToMany(cascade = {CascadeType.ALL})
    private List<Projeto> projetos;
    
    

    public Integer getId() {
        return id;
    }

    public void setId(Integer id) {
        this.id = id;
    }

    public List<Projeto> getProjetos() {
        return projetos;
    }

    public void setProjetos(List<Projeto> projetos) {
        this.projetos = projetos;
    }

    public Integer getTicketNumero() {
        return ticketNumero;
    }

    public void setTicketNumero(Integer ticketNumero) {
        this.ticketNumero = ticketNumero;
    }
}  



public class teste {

    public static void main(String[] args) {
        Ticket ticket = new Ticket();
        ticket.setTicketNumero(new Integer(4101));
        
        List<Ticket> tickets = new LinkedList<Ticket>();
        
        Projeto projeto = new Projeto();
        projeto.setNome("Teste2");
        projeto.setTickets(tickets);

        List<Projeto> projetos = new LinkedList<Projeto>();
        projetos.add(projeto);

        ticket.setProjetos(projetos);

        tickets.add(ticket);
        
        DaoFactory daoFactory = new DaoFactory(HibernateUtil.getSession());
        Dao dao = daoFactory.getProjetoDao();

        daoFactory.beginTransaction();
        dao.save(projeto);
        daoFactory.commit();
    }



public class Dao<T> {
    
        private Session session;
        private final Class<T> classe;
        
        Dao(Session session, Class<T> classe) {
              this.session = session;
              this.classe = classe;
        }
        
        protected Session getSession() {
              return session;
        }

        
        public void save(T u) {
              this.session.save(u);
        }                        
}


public class DaoFactory {

    private final Session session;
    private Transaction transaction;
    

    public DaoFactory(Session session) {
        this.session = session;
    }

    public void beginTransaction() {
        this.transaction = this.session.beginTransaction();
    }

    public void commit() {
        this.transaction.commit();
        this.transaction = null;
    }


    

    public Dao<Projeto> getProjetoDao() {
        return new Dao<Projeto>(this.session, Projeto.class);
    }
    
    public Dao<Ticket> getTicketDao() {
        return new Dao<Ticket>(this.session, Ticket.class);
    }
    
}

eu rodei aqui, e tudo está salvo corretamente em três tabelas…duas de objetos e uma de relacionamento…

B

No seu banco de dados vc tem as 3 tableas…certo? e de relacionamento tem como chave o id das outras duas?

T

sim…o próprio hibernate trata isso…ele se encarrega das chaves…

B

Vc criou o banco ou deixou o hibernate criar?

T

a base vocÊ cria, só ela…as tabelas o hibernate cria…

B

Então, fiz o mesmo teste que vc…porém na hora que gerei as tabelas, como no seu exemplo não é utlizado a annotation @JoinTable, ele não cria a tabela de relacionamento.

Uso o seguinte código para gerar o banco a partir do hibernate

public class GeraBanco {

	public static void main(String[] args) {
		Configuration conf = new AnnotationConfiguration();
		conf.configure();
		
		SchemaExport export = new SchemaExport(conf);
		export.create(true, true);
	}
	
}

sendo assim ele salva…mais salva da mesma maneira que antes…nas duas tabelas…porém como não existe a de relacionamento ele não tem onde inserir.

T

errado…não precisei utilizar o GeraBanco, mas se quiser também não tem problema…ele gera a tabela de relacionamento sim, a não ser que voce não esteja mapeando de maneira correta…esse projeto que eu fiz, rodei perfeitamente com as 3 tabelas…não há necessidade de rodar o GeraBanco, qdo inicia sua aplicação se não houver as tabelas o hibernate cria pra vc…

B

Cara nem acredito…funcionou…

Apaguei tudo, apaguei o database.
Apesar de eu não conseguir gerar as tabelas…simplesmente rodando a aplicação, pois eu devo ter que colocar alguma opção no hibernate.cfg.xml

Bom rodando o GeraBanco ele criou tudo direitinho
Realmente não precisa dos @JoinTable
O que fico me perguntando é para que servem, mais isso vou deixar para entender depois.

Thiago, vlw…já tava há alguns dias tentando decifrar esse problema.

flw

Criado 27 de abril de 2009
Ultima resposta 27 de abr. de 2009
Respostas 16
Participantes 2