Denovo Relacionamento many-to-many Hibernate Annotations

3 respostas
O

Bom dia pessoal. Antes de mais nada, pelo que observei o forum esta cheio de topicos a respeito do assunto que vou pedir a ajuda de vcs, mas, eu nao consegui resolver o meu problema e por isso resolvi abrir mais um topico. Por favor moderadores me desculpem.

O meu problema é o seguinte. Tenho duas entitys: Aluno e Turma. Elas tem um relacionamento many-to-many bidirecionais. A entity Turma é a dona do relacionamento. Pela entity Turma ser a owner assim que ela for persistida a entity Aluno tambem tem que ser persistida. Mas a entity Aluno nao é persistida e nem a tabela TurmaAluno que contem as chaves primary de Aluno e Turma.
Abaixo esta o codigo de cada entity e a classe que executa a persistencia.

A Entity Aluno:

@Entity
@Table(name = "Aluno")
public class Aluno extends Pessoa implements Serializable {
	
	
	private String matricula;
	private Set<Turma> turmas;
	
	@Column(name = "matricula", length = 10)
	public String getMatricula() {
		return matricula;
	}

	public void setMatricula(String matricula) {
		this.matricula = matricula;
	}
	
	@ManyToMany (mappedBy = "alunos", 
			targetEntity = br.com.mgf.modelo.Turma.class )
	public Set<Turma> getTurmas() {
		return turmas;
	}

	public void setTurmas(Set<Turma> turmas) {
		this.turmas = turmas;
	}
	

}

Agora a Entity Turma:

@Entity
@Table(name = "Turma")
public class Turma implements Serializable {
	
	private Long idTurma;
	private String nomeTurma;
	private Set<Aluno> alunos;
	
	@Id
	@GeneratedValue(strategy = GenerationType.IDENTITY)
	public Long getIdTurma() {
		return idTurma;
	}
	public void setIdTurma(Long idTurma) {
		this.idTurma = idTurma;
	}
	
	@Column(name = "nomeTurma", length = 20)
	public String getNomeTurma() {
		return nomeTurma;
	}
	
	public void setNomeTurma(String nomeTurma) {
		this.nomeTurma = nomeTurma;
	}
	
	@ManyToMany(targetEntity = br.com.mgf.modelo.Aluno.class, cascade = {CascadeType.PERSIST, CascadeType.MERGE})
	@JoinTable(name = "TurmaAluno",
			joinColumns = {@JoinColumn(name = "idTurmaFk")}, inverseJoinColumns = {@JoinColumn(name="idAlunoFk")})
	public Set<Aluno> getAlunos() {
		return alunos;
	}
	public void setAlunos(Set<Aluno> alunos) {
		this.alunos = alunos;
	}
	

}

Agora a classe que executa a persistencia…

public class Dao {

	/**
	 * @param args
	 */
	
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Session session = new HibernateUtil().getSession();
		Transaction tx = session.beginTransaction();
		
		
		Aluno aluno = new Aluno();
		Turma turma = new Turma();
		
		
		
		Dao dao = new Dao();
		aluno = (Aluno) dao.cadastraAluno();
		aluno.setTurmas(new HashSet<Turma>());
		aluno.getTurmas().add(turma);
		
		turma.setNomeTurma("Hello World");
		turma.setAlunos(new HashSet<Aluno>());
		turma.getAlunos().add(aluno);
		session.save(turma);
                tx.comit();
		session.close();
		
			
						
				
	}
		
	public Pessoa cadastraAluno(){
		
		Aluno aluno = new Aluno();
		Endereco endereco = new Endereco();
		
		aluno.setNome("Diego Junior");
		aluno.setTelefone("35-3522-8460");
		aluno.setEmail("[email removido]");
		aluno.setMatricula("20027293");
		endereco.setRua("Av: Amazonas");
		endereco.setBairro("Bela Vista");
		endereco.setNumero(663);
		endereco.setCep("37900-238");
		endereco.setCidade("Passos");
		endereco.setComplemento("Casa");
		endereco.setEstado("MG");
		endereco.setPessoa(aluno);
		aluno.setEndereco(endereco);
		return aluno;
		
	}
	
}

O que pode estar acontecendo? Obrigado

3 Respostas

Guto_Magalhaes

Cara, talvez seja no xml o problema. Tente o seguinte. Faça os relacionamentos no banco ao invez de fazer no hibernate. Vc sabe, many-to-many em modelagem de dados vc deve criar outra tabela, que ira receber as chaves de aluno e de turma. Ai, vc tira as relações do xml do hibernate e trata os atributos que usava para fazer as relações como propertyes normal. Se ocorrer uma violação, o proprio banco ira se proteger.

Espero ter ajudado. Se não, este material pode te ajudar.

Falow ae.

O

Conseguir solucionar, mas nao entendi o erro que deu…
Se acaso eu declarar o relacionamento assim:

@ManyToMany(targetEntity = br.com.mgf.modelo.Aluno.class)
	@JoinTable(name = "TurmaAluno",
			joinColumns = {@JoinColumn(name = "idTurmaFk")}, inverseJoinColumns = {@JoinColumn(name="idAlunoFk")})
	@Cascade(CascadeType.PERSIST)
	public Set<Aluno> getAlunos() {
		return alunos;
	}

E eu persistir assim:

public class Dao {

	/**
	 * @param args
	 */
	
	
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		Session session = new HibernateUtil().getSession();
		Transaction tx = session.beginTransaction();
		
		
		Aluno aluno = new Aluno();
		Turma turma = new Turma();
		
		Dao dao = new Dao();
		aluno = (Aluno) dao.cadastraAluno();
		aluno.setTurmas(new HashSet<Turma>());
		aluno.getTurmas().add(turma);
		
		turma.setNomeTurma("Hello World");
		turma.setAlunos(new HashSet<Aluno>());
		turma.getAlunos().add(aluno);
			
		session.save(turma);
		tx.commit(); // Da erro aqui
		session.close();
		
	}
		
	public Pessoa cadastraAluno(){
		
		Aluno aluno = new Aluno();
		Endereco endereco = new Endereco();
		
		aluno.setNome("Diego Junior");
		aluno.setTelefone("35-3522-8460");
		aluno.setEmail("[email removido]");
		aluno.setMatricula("20027293");
		endereco.setRua("Av: Amazonas");
		endereco.setBairro("Bela Vista");
		endereco.setNumero(663);
		endereco.setCep("37900-238");
		endereco.setCidade("Passos");
		endereco.setComplemento("Casa");
		endereco.setEstado("MG");
		endereco.setPessoa(aluno);
		aluno.setEndereco(endereco);
		return aluno;
		
	}
	

}

O erro é esse:

Exception in thread "main" org.hibernate.TransientObjectException: object references an unsaved transient instance - save the transient instance before flushing: br.com.mgf.modelo.Aluno

Mas se eu mudar o CascadeType de CascadeType.PERSIST para CascadeType.SAVE_UPDATE ele nao da erro e persiste normalmente…

Pelo que li. O CascadeType.PERSIST é assim: os objetos associados vão ser inseridos automaticamente quando o objeto “pai” for inserido;

E o CascadeType.SAVE_UPDATE: os objetos associados vão ser inseridos ou atualizados automaticamente quando o objeto “pai” for inserido ou atualizado;

Para a persistencia entre esse relacionamento que eu coloquei o Cascade nao poderia ser qualquer um desses que falei?

_Zell_

Olá pessoal.
Eu estou com esse mesmo problema e só consegui recolver usando CascadeType.ALL. Só que o problema disso é que quando ele apaga qualquer uma das duas entidades relacionadas ele apaga as duas. Sendo que eu quero apenas retirar o relacionamento, que no caso do exemplo desde tópico seria um registro da tabela AlunoTurma. Até agora eu não to conseguindo resolver isso -.-

Se alguém puder dar uma luz ai…

Abraço!

Criado 1 de agosto de 2007
Ultima resposta 3 de out. de 2011
Respostas 3
Participantes 3