Erro Hibernate com mapeamento ManyToMany

Pessoal,

Estou tentando inserir no BD um objeto com relacionamento ManyToMany, mas não estou conseguindo, espero que possam me ajudar.

Criei as duas tabelas no BD e depois a tabela associtativa, junto com as foreign keys.

Depois modelei as duas classes em java, adicionando as anotações do relacionamento m:n que surgiu.
Porém na hora de inserir, se eu seto todos os dados do objeto Ferias e depois coloco esse objeto na coleção ferias da classe Colaborador, nada acontece, só mostra um erro dizendo que não consegue salvar no BD, apenas isso.
Se eu faço ao contrário, seto o colaborador com os dados recuperados do BD com o ID dele e depois jogo esse objeto colaborador dentro da coleção da classe Férias, dá o seguinte erro: object references an unsaved transient instance - save the transient instance before flushing: catalogo.modelo.Ferias

Não sei o que pode ser, já mexi no BD, no xml do Hibernate, já testei de varias maneiras, já setei a o objeto ferias depois colaborador e nada até agora, se algume puder me ajudar, agradeço.

Classe COLABORADOR:

...
@Entity
@Table(name = "colaborador", schema = "catalogo")
@Inheritance(strategy = InheritanceType.JOINED)
public class Colaborador implements Serializable
{
   ...
   @ManyToMany(fetch=FetchType.EAGER) 
   @JoinTable(name="colaborador_ferias", schema="catalogo", 
               joinColumns=@JoinColumn(name="id_colaborador"), 
               inverseJoinColumns=@JoinColumn(name="id_ferias")) 
   @Fetch(FetchMode.JOIN)
   @Cascade(CascadeType.ALL)
   private Collection<Ferias> ferias; 

   ...
   public Collection<Ferias> getFerias() {
        return ferias;
    }

    public void setFerias(Collection<Ferias> ferias) {
        this.ferias = ferias;
    }  
...
}

Classe FERIAS:

...
@Entity
@Table(name = "ferias", schema = "catalogo")
public class Ferias implements Serializable
{
  ...
  @ManyToMany(fetch=FetchType.LAZY) 
  @JoinTable(name="colaborador_ferias", schema="catalogo", 
               joinColumns={@JoinColumn(name="id_ferias")}, 
               inverseJoinColumns={@JoinColumn(name="id_colaborador")}) 
  @Fetch(FetchMode.JOIN)
  @Cascade(CascadeType.ALL)
  private Collection<Colaborador> colaboradores;

  public Collection<Colaborador> getColaboradores() {
        return colaboradores;
    }

    public void setColaboradores(Collection<Colaborador> colaboradores) {
        this.colaboradores = colaboradores;
    }   
...
}

ACTION

...

FeriasForm feriasForm = (FeriasForm)form;
        
        Colaborador colaborador = new Colaborador();                
        Ferias ferias = new Ferias();
                
        int idColaborador = Integer.parseInt(feriasForm.getIdColaborador());
        GenericDAO colaboradorDao = new GenericDAO(Colaborador.class);
        colaborador = (Colaborador) colaboradorDao.carregarPeloId(idColaborador);        
        
        ferias.setTipo(feriasForm.getTipo());
        ferias.setExercicio(feriasForm.getExercicio());
        ferias.setPeriodo1(feriasForm.getPeriodo1());
        ferias.setInicio1(ConverterData.converteData(feriasForm.getInicio1()));        
        ferias.setPeriodo2(feriasForm.getPeriodo2());
        ferias.setInicio2(ConverterData.converteData(feriasForm.getInicio2()));        
        ferias.setObs(feriasForm.getObs());
        
        /*ferias.setColaboradores(new ArrayList<Colaborador>()); 
        ferias.getColaboradores().add(colaborador);*/
        
        colaborador.setFerias(new ArrayList<Ferias>());
        colaborador.getFerias().add(ferias);        
        
        
        /*int idColaborador = Integer.parseInt(feriasForm.getIdColaborador());
        GenericDAO colaboradorDao = new GenericDAO(Colaborador.class);
        colaborador = (Colaborador) colaboradorDao.carregarPeloId(idColaborador);        
        //ferias.setColaborador(colaborador);
        ferias.setColaboradores(new ArrayList<Colaborador>()); 
        ferias.getColaboradores().add(colaborador);*/
        
        GenericDAO dao = new GenericDAO(Ferias.class);               
        
        try {
            dao.salvar(colaborador);
            retorno = "sucesso";
            msg = "As f&eacute;rias do funcion&aacute;rio foram cadastradas com sucesso!";
        } 
        catch (Exception e) {
            retorno = "erro";
            msg = "N&atilde;o foi poss&iacute;vel salvar as f&eacute;rias do funcion&aacute;rio!" + e.getMessage().toString();
        }

...

cara,

como seu mapeamento é bidirecional, vc tem que fazer o seguinte

colaborador.setFerias(new ArrayList<Ferias>());  
colaborador.getFerias().add(ferias);

ferias.setColaborador(new ArrayList<Colaborador>());
ferias.getColaborador()add(colaborador);

t+

Alisson,

Fiz o que voce falou, setei tambem a coleção de colaboradores na classe ferias. Agora deu o mesmo erro que dava quando eu tentava inserir setando o objeto Ferias (fazendo ao contrario do que está codificado acima).
O erro mostrado é apenas esse:

could not insert: [catalogo.modelo.Ferias]

cara,

posta o erro completo ai

Só apareceu esse.
Como mostro o erro todo?

no seu catch, coloque e.printStackTrace(); e poste aqui.

Hoje em dia, faço assim:

msg = "N&atilde;o foi poss&iacute;vel salvar as f&eacute;rias do funcion&aacute;rio!" + e.getMessage().toString();         

Quando coloco essa linha:

e.printStackTrace();

Não mostra nada e o NetBeans ainda fala que eu devo remover essa linha com o printStackTrace
Como faço dentro do try e catch para mostrar o erro completo?

cara, vc tem que fazer assim

catch (Exception e) {  
            retorno = "erro";  
            msg = "Não foi possível salvar as férias do funcionário!" + e.getMessage().toString();  
            e.printStackTrace();
        }

Coloquei assim (como já havia feito anteriormente):

catch (Exception e) { retorno = "erro"; msg = "Não foi possível salvar as férias do funcionário!" + e.getMessage().toString(); e.printStackTrace(); }

E continua mostrando apenas isso:

Não foi possível salvar as férias do funcionário!could not insert: [catalogo.modelo.Ferias]

cara,
estranho isso, faz um debug ai e ve pq nao está sendo mostrado o log de erro.

t+

Alisson,

Nada, infelizmente. Depurei e não aconteceu nada tambem, só se fiz errado.

cara,

tem logica isso não, tem algo errado ai. pq sem ele log, nao tem como te ajudar

Não tem outra maneira de eu ver o erro completo nao?

faz o seguinte, coloca um breakponit no seu catch, e qdo ele entrar nele, verifique o conteudo da variavel do objeto Exception.

Já fiz isso, mas não consegui continuar a depuração, vou tentar de novo aqui…

A unica coisa que consegui foi isso:

org.hibernate.exception.GenericJDBCException: could not insert: [catalogo.modelo.Ferias]

Só aparece isso como valor da variavel na linha que dei breakpoint

é cara, essa sua aplicação ta extraissimaaaa. pq sem saber o log de erro, fica dificil de te ajudar

cara,

fiz um exemplo para te ajudar, segue ai

import java.io.Serializable;
import javax.persistence.*;
import java.util.List;


/**
 * The persistent class for the table1 database table.
 * 
 */
@Entity
@Table(name="table1")
public class Table1 implements Serializable {
	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private int idtable1;

	private String descricao;

	//bi-directional many-to-many association to Table2
	@ManyToMany(mappedBy="table1s", cascade = CascadeType.ALL)
	private List<Table2> table2s;

    public Table1() {
    }

	public int getIdtable1() {
		return this.idtable1;
	}

	public void setIdtable1(int idtable1) {
		this.idtable1 = idtable1;
	}

	public String getDescricao() {
		return this.descricao;
	}

	public void setDescricao(String descricao) {
		this.descricao = descricao;
	}

	public List<Table2> getTable2s() {
		return this.table2s;
	}

	public void setTable2s(List<Table2> table2s) {
		this.table2s = table2s;
	}
	
}

import java.io.Serializable;
import javax.persistence.*;
import java.util.List;


/**
 * The persistent class for the table2 database table.
 * 
 */
@Entity
@Table(name="table2")
public class Table2 implements Serializable {
	private static final long serialVersionUID = 1L;

	@Id
	@GeneratedValue(strategy=GenerationType.IDENTITY)
	private int idtable2;

	private String descricao;

	//bi-directional many-to-many association to Table1
    @ManyToMany(cascade = CascadeType.ALL)
	@JoinTable(name="table1table2", 
			   joinColumns={@JoinColumn(name="idtable2")}, 
			   inverseJoinColumns={@JoinColumn(name="idtable1")})
	private List<Table1> table1s;

    public Table2() {
    }

	public int getIdtable2() {
		return this.idtable2;
	}

	public void setIdtable2(int idtable2) {
		this.idtable2 = idtable2;
	}

	public String getDescricao() {
		return this.descricao;
	}

	public void setDescricao(String descricao) {
		this.descricao = descricao;
	}

	public List<Table1> getTable1s() {
		return this.table1s;
	}

	public void setTable1s(List<Table1> table1s) {
		this.table1s = table1s;
	}
	
}
public class Teste {
	public static void main(String[] args) {
		EntityManager entityManager = Persistence.createEntityManagerFactory("bingo").createEntityManager();
		
		Table1 table1 = new Table1();
		table1.setDescricao("teste1");
		table1.setTable2s(new ArrayList<Table2>());
		
		Table2 table2 = new Table2();
		table2.setDescricao("teste2");
		table2.setTable1s(new ArrayList<Table1>());
		
		table1.getTable2s().add(table2);
		table2.getTable1s().add(table1);
		
		entityManager.getTransaction().begin();
		entityManager.persist(table1);
		entityManager.getTransaction().commit();
        }
}

PS: coloca o jar do log4j que ele pode te ajudar a mostrar o log de erro.

t+

Alterei algumas coisas, seguindo o exemplo que voce deu e nao funcinou tambem. Estou tentando colocar o log4j para rodar aqui, se conseguir eu posto.

COLABORADOR:

@ManyToMany(mappedBy = "colaboradores", cascade = javax.persistence.CascadeType.ALL) private List<Ferias> ferias;

FERIAS:

@ManyToMany(cascade = CascadeType.ALL) @JoinTable(name="colaborador_ferias", schema = "catalogo", joinColumns={@JoinColumn(name="id_ferias")}, inverseJoinColumns={@JoinColumn(name="id_colaborador")}) private List<Colaborador> colaboradores;

ACTION:

FeriasForm feriasForm = (FeriasForm)form;
        
        Colaborador colaborador = new Colaborador();                
        Ferias ferias = new Ferias();
                
        /*int idColaborador = Integer.parseInt(feriasForm.getIdColaborador());
        GenericDAO colaboradorDao = new GenericDAO(Colaborador.class);
        colaborador = (Colaborador) colaboradorDao.carregarPeloId(idColaborador);    */
        colaborador.setId(52);
        colaborador.setFerias(new ArrayList<Ferias>());
        
        ferias.setTipo(feriasForm.getTipo());
        ferias.setExercicio(feriasForm.getExercicio());
        ferias.setPeriodo1(feriasForm.getPeriodo1());
        ferias.setInicio1(ConverterData.converteData(feriasForm.getInicio1()));        
        ferias.setPeriodo2(feriasForm.getPeriodo2());
        ferias.setInicio2(ConverterData.converteData(feriasForm.getInicio2()));        
        ferias.setObs(feriasForm.getObs());
        ferias.setColaboradores(new ArrayList<Colaborador>()); 
        
        /*ferias.setColaboradores(new ArrayList<Colaborador>()); 
        ferias.getColaboradores().add(colaborador);*/
                
        colaborador.getFerias().add(ferias);                         
        ferias.getColaboradores().add(colaborador); 
        
        
        /*int idColaborador = Integer.parseInt(feriasForm.getIdColaborador());
        GenericDAO colaboradorDao = new GenericDAO(Colaborador.class);
        colaborador = (Colaborador) colaboradorDao.carregarPeloId(idColaborador);        
        //ferias.setColaborador(colaborador);
        ferias.setColaboradores(new ArrayList<Colaborador>()); 
        ferias.getColaboradores().add(colaborador);*/
        
        GenericDAO dao = new GenericDAO(Ferias.class);               
        
        try {
            dao.salvar(colaborador);
            retorno = "sucesso";
            msg = "As f&eacute;rias do funcion&aacute;rio foram cadastradas com sucesso!";
        } 
        catch (Exception e) {                     
            retorno = "erro";    
            msg = "Não foi possível salvar as férias do funcionário! " + e.getMessage().toString();    
            e.printStackTrace();  
        }          

BANCO DE DADOS
tab_ferias
id_ferias
periodo
ano

tab_colaborador
id_colaborador
dados do colaborador …

tab_colaborador_ferias
id_colaborador
id_ferias

Acho que está tudo certo né? Banco de dados e as classes?

Vou tentar ver o que está acontecendo com o0 log4j

cara,

o problema deve ser o seguinte, no exemplo q eu te passei, qdo se faz o insert, ele faz insert nas duas entidades e no seu caso vc quer trazer um colaborador que ja existe e vincular a ferias, nesse caso deve ser diferente o mapeamento.

coloca o log4j ai e ve o erro q vai da, q eu vou fazer um teste aqui no exemplo q eu te passei.

t+