[RESOLVIDO] JPA c/ Hibernate - 2 tabs, N aluno p/ 1 professor, sem erros + n cria corretamente

[code]package br.com.escola.entity;

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

import javax.persistence.CascadeType;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name=“tb_pai”)
public class Pai {

@Id
@GeneratedValue
private Integer idPai;
private String nome;

@OneToMany(cascade = {CascadeType.PERSIST}) 
private List<Aluno> alunos = new ArrayList<Aluno>();

public void setAlunos(List<Aluno> alunos) {
	this.alunos = alunos;
}

public List<Aluno> getAlunos() {
	return alunos;
}

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

public String getNome() {
	return nome;
}

public void setIdPai(Integer idPai) {
	this.idPai = idPai;
}

public Integer getIdPai() {
	return idPai;
}

}

package br.com.escola.entity;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name=“tb_aluno”)
public class Aluno {

@Id
@GeneratedValue
private Integer idAluno;

private Integer idPai;

@JoinColumn(name="idPai", referencedColumnName = "idPai", insertable = false, updatable = false) //@JoinColumn(name="idPai") 
@ManyToOne
private Pai pai;

public Integer getIdAluno() {
	return idAluno;
}

public void setIdAluno(Integer idAluno) {
	this.idAluno = idAluno;
}

public Integer getIdPai() {
	return idPai;
}

public void setIdPai(Integer idPai) {
	this.idPai = idPai;
}

public Pai getPai() {
	return pai;
}

public void setPai(Pai pai) {
	this.pai = pai;
}

}

package br.com.escola.teste;

import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;

public class Teste {

/**
 * @param args
 */
public static void main(String[] args) {
	EntityManagerFactory factory = Persistence.createEntityManagerFactory("Escola");
	factory.close();
}

}

[/code]

Ele gera três tabelas mas não funcionam adequadamente. Vide anexo:

TENTEI TAMBÉM DA SEGUINTE MANEIRA:

[code]package br.com.escola.entity;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name=“tb_aluno”)
public class Aluno {

@Id
@GeneratedValue
private Integer idAluno;

private Integer idPai;

@JoinColumn(name="idPai", referencedColumnName = "idPai", insertable = false, updatable = false) //@JoinColumn(name="idPai") 
@ManyToOne
private Pai pai;

public Integer getIdAluno() {
	return idAluno;
}

public void setIdAluno(Integer idAluno) {
	this.idAluno = idAluno;
}

public Integer getIdPai() {
	return idPai;
}

public void setIdPai(Integer idPai) {
	this.idPai = idPai;
}

public Pai getPai() {
	return pai;
}

public void setPai(Pai pai) {
	this.pai = pai;
}

}

[/code]

[code]package br.com.escola.entity;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.Table;

@Entity
@Table(name=“tb_pai”)
public class Pai {

@Id
@GeneratedValue
private Integer idPai;
private String nome;

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

public String getNome() {
	return nome;
}

public void setIdPai(Integer idPai) {
	this.idPai = idPai;
}

public Integer getIdPai() {
	return idPai;
}

}
[/code]

Daí ele criou duas tabelas, porém o relacionamento não funcionando corretamente.

O QUE EQUIVALENTE NO SQL É:

CREATE TABLE `escola`.`tbl_aluno` ( `idAluno` INTEGER UNSIGNED NOT NULL AUTO_INCREMENT, `nomeAluno` VARCHAR(45) NOT NULL, `idPaiFk` INTEGER UNSIGNED NOT NULL, PRIMARY KEY (`idAluno`), CONSTRAINT `idPaiFk` FOREIGN KEY `idPaiFk` (`idPaiFk`) REFERENCES `tbl_pai` (`idPai`) ON DELETE RESTRICT ON UPDATE RESTRICT ) ENGINE = InnoDB;

Dá primeira vez, ele criou as 2 tabelas, porque você fez o relacionamento dos dois lados. Tanto no lado Pai, quanto no lado Aluno. Quando você coloca assim, ele entende que são relacionamentos independentes (não tem relação um com o outro), ai nesse caso, você precisa usar dentro da anotation a propriedade mappedBy, dessa forma, o hibernate entende que apesar do relacionamento estar dos dois lados, é o mesmo relacionamento e não cria a tabela auxiliar e sim a chave estrangeira. Não tô em casa, se não te ajudava com algum exemplo…

Mas da segunda maneira, deveria funcionar corretamente. Mesmo deletando o banco e mandando o hibernate criar, ele continua criando uma tabela auxiliar?

Olá, valeu pela ajuda…

Pois é, pensei o mesmo que dá segunda maneira, foi a primeira maneira que tentei mas não funcionou, recrei a base de dados com o Hibernate JPA e nada…

Vou testar usando o mappedBy…

REALMENTE… ISSO DEVERIA FUNCIONAR, EU ACHO:

[code]package br.com.escola.entity;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name=“tb_aluno”)
public class Aluno {

@Id
@GeneratedValue
private Integer idAluno;

private Integer idPai;

@JoinColumn(name="idPai", referencedColumnName = "idPai", insertable = false, updatable = false, nullable = false) //@JoinColumn(name="idPai") 
@ManyToOne
private Pai pai;

public Integer getIdAluno() {
	return idAluno;
}

public void setIdAluno(Integer idAluno) {
	this.idAluno = idAluno;
}

public Integer getIdPai() {
	return idPai;
}

public void setIdPai(Integer idPai) {
	this.idPai = idPai;
}

public Pai getPai() {
	return pai;
}

public void setPai(Pai pai) {
	this.pai = pai;
}

}[/code]

FIZ PEQUENAS MUDANÇAS, MESMO ASSIM CONTINUA NÃO FUNCIONANDO O RELACIONAMENTO, NAO É CRIADA A CHAVE ESTRANGEIRA CORRETAMENTE:

[code]package br.com.escola.entity;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name=“tb_aluno”)
public class Aluno {

@Id
@GeneratedValue
private Integer idAluno;
private Integer idPaiFk;
private String nome;

@JoinColumn(name="idPaiFk",
			referencedColumnName = "idPai", 
			insertable = false, 
			updatable = false, 
			nullable = false
) 
@ManyToOne
private Pai pai = new Pai();

public Integer getIdAluno() {
	return idAluno;
}

public void setIdAluno(Integer idAluno) {
	this.idAluno = idAluno;
}

public Integer getIdPaiFk() {
	return idPaiFk;
}

public void setIdPaiFk(Integer idPaiFk) {
	this.idPaiFk = idPaiFk;
}

public Pai getPai() {
	return pai;
}

public void setPai(Pai pai) {
	this.pai = pai;
}

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

public String getNome() {
	return nome;
}

}[/code]

MAIS TENTATIVAS:

[code]package br.com.escola.entity;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name=“tb_aluno”)
public class Aluno {

@Id
@GeneratedValue
private Integer idAluno;
//private Integer idPaiFk;
private String nome;

/*@JoinColumn(name="idPaiFk",
			referencedColumnName = "pai.idPai", 
			insertable = false, 
			updatable = false, 
			nullable = false
) */
@ManyToOne
private Pai pai = new Pai();

public Integer getIdAluno() {
	return idAluno;
}

public void setIdAluno(Integer idAluno) {
	this.idAluno = idAluno;
}

/* public Integer getIdPaiFk() {
return idPaiFk;
}

public void setIdPaiFk(Integer idPaiFk) {
	this.idPaiFk = idPaiFk;
}*/

public Pai getPai() {
	return pai;
}

public void setPai(Pai pai) {
	this.pai = pai;
}

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

public String getNome() {
	return nome;
}

}[/code]

Vou te mostrar um exemplo que tenho aqui.

Tenho uma entidade Conta e uma Movimentação. Cada Movimentação é referente a uma Conta (chave estrangeira). Mapeie da seguinte maneira:

[code]@Entity
public class Movimentacao {

// outros atributos

@ManyToOne
private Conta conta;

//getters and setters
}[/code]

E para poder ter uma lista de movimentações por conta, está da seguinte maneira:

[code]@Entity
public class Conta {

//outros atributos
@OneToMany(mappedBy=“conta”)
private List<Movimentacao> movimentacoes = new ArrayList<Movimentacao>();

}[/code]

Ele cria como chave estrangeira. No mappedBy você coloca o lado fraco da relação. Movimentação é o lado forte, já que ela tem uma relação com Conta, mas Conta não tem com ela (conceito de chave estrangeira)

Vê se te ajuda.

Observação, dá um drop database, e faz um modelo simples só para testar isso, se funcionar, depois coloca no seu projeto

Puxa que estranho, continua não funcionando… Fiz do jeitinho que você falou…

[code]package br.com.escola.entity;

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

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.Table;

@Entity
@Table(name=“tb_pai”)
public class Pai {

@Id
@GeneratedValue
private Integer idPai;
private String nome;

@OneToMany(mappedBy="pai")
List<Aluno> alunosList = new ArrayList<Aluno>();

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

public String getNome() {
	return nome;
}

public void setIdPai(Integer idPai) {
	this.idPai = idPai;
}

public Integer getIdPai() {
	return idPai;
}

public void setAlunosList(List<Aluno> alunosList) {
	this.alunosList = alunosList;
}

public List<Aluno> getAlunosList() {
	return alunosList;
}

}[/code]

[code]package br.com.escola.entity;

import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.Id;
import javax.persistence.ManyToOne;
import javax.persistence.Table;

@Entity
@Table(name=“tb_aluno”)
public class Aluno {

@Id
@GeneratedValue
private Integer idAluno;
//private Integer idPaiFk;
private String nome;

/*@JoinColumn(name="idPaiFk",
			referencedColumnName = "pai.idPai", 
			insertable = false, 
			updatable = false, 
			nullable = false
) */
@ManyToOne
//@JoinColumn(name="idPai")
private Pai pai;

public Integer getIdAluno() {
	return idAluno;
}

public void setIdAluno(Integer idAluno) {
	this.idAluno = idAluno;
}

/* public Integer getIdPaiFk() {
return idPaiFk;
}

public void setIdPaiFk(Integer idPaiFk) {
	this.idPaiFk = idPaiFk;
}*/

public Pai getPai() {
	return pai;
}

public void setPai(Pai pai) {
	this.pai = pai;
}

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

public String getNome() {
	return nome;
}

}[/code]

Posta ai teu persistence.xml

Se a propriedade hibernate.hbm2ddl.auto tiver como update, ele cria a chave primária, mas não apaga a tabela auxiliar. Já tentou dropar o banco e criar novamente?

Você não está usando nenhum mapeamento em xml também né? Apenas por anottations correto?

[quote=javablue]Posta ai teu persistence.xml

Se a propriedade hibernate.hbm2ddl.auto tiver como update, ele cria a chave primária, mas não apaga a tabela auxiliar. Já tentou dropar o banco e criar novamente?

Você não está usando nenhum mapeamento em xml também né? Apenas por anottations correto?[/quote]

Estava create, mas dropei as tabelas e as criei usando update e não funcionou. Não há tabela auxiliar. Já dropei a base de dados e nada. Estou
usando puramente anotação. Vide meu persistence.xml:

[code]<?xml version=“1.0” encoding=“UTF-8”?>
<persistence xmlns="http://java.sun.com/xml/ns/persistence"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://java.sun.com/xml/ns/persistence http://java.sun.com/xml/ns/persistence/persistence_1_0.xsd"
version=“1.0”>

&lt;persistence-unit name="Escola" transaction-type="RESOURCE_LOCAL"&gt;
	&lt;provider&gt;
		org.hibernate.ejb.HibernatePersistence
	&lt;/provider&gt;
	&lt;properties&gt;
		&lt;property name="hibernate.dialect" value="org.hibernate.dialect.MySQLMyISAMDialect" /&gt;
		&lt;property name="hibernate.hbm2ddl.auto" value="update" /&gt;
		&lt;property name="javax.persistence.jdbc.driver" value="com.mysql.jdbc.Driver" /&gt;
		&lt;property name="javax.persistence.jdbc.user" value="root" /&gt;
		&lt;property name="javax.persistence.jdbc.password" value="root" /&gt;
		&lt;property name="javax.persistence.jdbc.url" value="jdbc:mysql://localhost:3306/Escola" /&gt;
	&lt;/properties&gt;
&lt;/persistence-unit&gt;

</persistence>[/code]

Puxa, acho que agora está funcionando, fiz uma mudança no persistence.xml para:

Testando…

JavaBlue, problema solucionado, era aquela linha mesma, questões de MyISAM (sem relacionamento) você deu a dica do persistence.xml e acabei matando a charada rs. Valeu mesmo kra. Abração.

AS.

Só consegui entrar no guj agora.

Quando vi teu persistence.xml, também ia sugerir isso.

Que bom que funcionou