Dúvida hibernate com @ManyToMany, @ManyToOne, @OneToMany, etc

É o seguinte pessoal, estou desenvolvendo um sisteminha básico pra pizzaria, para trabalho de faculdade, nesse sistema eu tenho a classe Pizza, Bebidas, Mesa, Fornecedor, Funcionario, Ingrediente, e outras que ainda estou desenvolvendo…

Estou usando o hibernate para criar as tabelas e tal, então, sei que é besteira mais estou em dúvida em como usar os @ManyToMany, esse negocio de chave estrangeira…

No meu caso Uma Pizza tem vários sabores, e um sabor pode estar em várias pizzas, seria um @ManyToMany que eu declararia la na minha classe, declarei assim:

	@ManyToMany(fetch=FetchType.EAGER)
	@JoinColumn(name="id_sabor")
	private List<Sabor> sabores;

Coloquei essa parte de fetch e tal porque tava lendo umas coisas e peguei o exemplo, não sei o porque de eu usar isso kkk…

Minha dúvida é em que situações eu uso @ManyToOne, @OneToMany, etc…
E tipo, se eu tenho uma variavel exemplo
Vou cadastrar um produto e esse produto tem um fornecedor, e um fornecedor pode ter vários produtos. Então na classe Produto oq eu declararia?

@ManyToOne @JoinColumn(name="id_fornecedor") Fornecedor fornecedor;

@ManyToOne ? Vários para um ou @OneToMany, nisso que estou confuso.

Como vocês me aconselham a fazer? obrigado!

Te aconselharia usar o @OneToMany pois vc terá de um sabor a vários.

Imagine a situação…

-> Um pai pode ter variois filhos…
-> Um filho só pode ter um pai…

Assim…

A Classe Pai terá um LISTA de Filho… dai você usa
@OneToMany(mappedBy=“nomeDaVariavelPaiDaClasseFilho”, cascade=CascadeType.ALL)
private List filhos;

Na Classe Filho terá um OBJETO Pai… dai você usa
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name=“idDaColunaPkDaClassePai”)

private Pai pai;

@OneToMany = Existem várias ocorrências da variável com essa anotação para essa classe
@ManyToOne = Esta classe só pode ter uma dessa variável, mas a variavel pode ter várias dessa classe;

1 curtida

[quote=Rafael_Leal]Imagine a situação…

-> Um pai pode ter variois filhos…
-> Um filho só pode ter um pai…

Assim…

A Classe Pai terá um LISTA de Filho… dai você usa
@OneToMany(mappedBy=“nomeDaVariavelPaiDaClasseFilho”, cascade=CascadeType.ALL)
private List filhos;

Na Classe Filho terá um OBJETO Pai… dai você usa
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name=“idDaColunaPkDaClassePai”)

private Pai pai;

@OneToMany = Existem várias ocorrências da variável com essa anotação para essa classe
@ManyToOne = Esta classe só pode ter uma dessa variável, mas a variavel pode ter várias dessa classe;
[/quote]

Entendi, obrigado!
Eu não usei esse mappedBy, pra que serve? E porque só usou ele na classe pai?

[quote=kvnallen][quote=Rafael_Leal]Imagine a situação…

-> Um pai pode ter variois filhos…
-> Um filho só pode ter um pai…

Assim…

A Classe Pai terá um LISTA de Filho… dai você usa
@OneToMany(mappedBy=“nomeDaVariavelPaiDaClasseFilho”, cascade=CascadeType.ALL)
private List filhos;

Na Classe Filho terá um OBJETO Pai… dai você usa
@ManyToOne(cascade=CascadeType.ALL)
@JoinColumn(name=“idDaColunaPkDaClassePai”)

private Pai pai;

@OneToMany = Existem várias ocorrências da variável com essa anotação para essa classe
@ManyToOne = Esta classe só pode ter uma dessa variável, mas a variavel pode ter várias dessa classe;
[/quote]

Entendi, obrigado!
Eu não usei esse mappedBy, pra que serve? E porque só usou ele na classe pai?[/quote]

Isso é questão de uni ou bi-direcionalidade se esse palavra existir!!!

usando o mappedBy no @OneToMany você tá dizendo pro hibernate que toda vez que carregar a Classe Pai do banco… a List filhos também ter que ser carregada… dai o Hibernate pega a pk(id) da Classe pai… vai no banco na tabela filho e carrega todos o objetos Filhos que tem a uma coluna fK com mesmo pk do pai.

1 curtida

Certo, eu não estava usando isso, mas peguei um exemplo aqui que dizia :

@Fetch(FetchMode.JOIN) servia da mesma coisa…

E se vc souber responder, pra que serve o @ManyToOne(fetch=FetchType.EAGER)

[quote=kvnallen]Certo, eu não estava usando isso, mas peguei um exemplo aqui que dizia :

@Fetch(FetchMode.JOIN) servia da mesma coisa…

E se vc souber responder, pra que serve o @ManyToOne(fetch=FetchType.EAGER)[/quote]

@Fetch(FetchMode.JOIN) fala para Hibernate deve executa uma sql com join entre a e b
se não ele faz uma sql para a e depois outra para b e poe os resultado de b dentro de a
Ele não substitue o mapedBy no @OneToMany

@ManyToOne(fetch=FetchType.EAGER): fala para o Hibernate que ele deve carregar a coleção b junto com a Classe a.
A tem BB e carregado no mesmo momento de A.

@ManyToOne(fetch=FetchType.LAZY): fala para o Hibernate que ele deve carregar a coleção b só é carregado quando você chamar o método getColeçãodeB() da classe a
A tem BB e carregado na chamada do a.getB().

Rafael_Leal estou com algumas dúvidas quanto ao mapeamento relacional de classes no Hibernate.

Meu contexto e o seguinte.

Tenho 3 tabelas: Aluno, Reserva e Livro.

Classe Aluno:


@Entity
@Table(name = "aluno", catalog = "baselibrus")
public class Aluno implements java.io.Serializable {

	private Integer idAluno;
	private List<Reserva> reservas;
        // atributos omitidos
	
	@Id
	@GeneratedValue(strategy = IDENTITY)
	@Column(name = "idAluno", unique = true, nullable = false)
	public Integer getIdAluno() {
		return idAluno;
	}

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

	
	
	@OneToMany(cascade = CascadeType.PERSIST, mappedBy = "aluno")
	public List<Reserva> getReservas() {
		return reservas;
	}

	public void setReservas(List<Reserva> reservas) {
		this.reservas = reservas;
	}
	
}

Classe Reserva:



@Entity
@Table(name = "reserva", catalog = "baselibrus")
public class Reserva implements java.io.Serializable {

	private Integer id;
        private Aluno aluno; 	
        private Livro livro; 
    
    
	

	@Id
	@GeneratedValue(strategy = IDENTITY)
	@Column(name = "id", unique = false, nullable = false)
	public Integer getId() {
		return this.id;
	}

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

	
	@ManyToOne
	@JoinColumn(name="idAluno", insertable = false, updatable = false)
	public Aluno getAluno() {
		return aluno;
	}

	public void setAluno(Aluno aluno) {
		this.aluno = aluno;
	}

	
	@ManyToOne
	@JoinColumn(name="idLivro", insertable = false, updatable = false)
	public Livro getLivro() {
		return livro;
	}

	public void setLivro(Livro livro) {
		this.livro = livro;
	}

}

Classe Livro:

@Entity
@Table(name = "livro", catalog = "baselibrus")
public class Livro implements java.io.Serializable {

	private Integer idLivro;
	private List<Reserva> reservas;
	
	@Id
	@GeneratedValue(strategy = IDENTITY)
	@Column(name = "idLivro", unique = true, nullable = false)
	public Integer getIdLivro() {
		return idLivro;
	}

	public void setIdLivro(Integer idLivro) {
		this.idLivro = idLivro;
	}

	
        @OneToMany(cascade = CascadeType.PERSIST, fetch=FetchType.EAGER,mappedBy ="livro")
	public List<Reserva> getReservas() {
		return reservas;
	}

	public void setReservas(List<Reserva> reservas) {
		this.reservas = reservas;
	}
}

Cara se você puder ajudar ficaria muito grato, o sistema está rodando “liso” só falta implemetar esse módulo que e o seguinte:

Tenho Alunos cadastrados e tenho Livros também.

Essa tabela Reserva serve para guardar a relação de livros e alunos.

Tipo: IdAluno - IdLivro
3 1
3 15
3 12

Não entendi… qual é o seu problema?
A Classe reserva não está salvando via Hibernate?

E porque o atribulo ID da classe Reserna não tá com a anotação Unique = true? Todo ID é único se não o campo em si não faz sentido…

E você tbm não é obrigado a criar um classe Reserva só para efetuar uma nova reserva… a não ser que você realmente precisa do campo ID para lógica do seu código. Senão você pode usar ManyToMany… em Livros e Aluno… (mas deixemos isso para depois se você realemente precisar)

Aproveitando o topico para falar sobre @ManytoMany

Ex:
Vou postar minhas classes que estão exatamente iguais às minhas tabelas do meu banco de dados.

Empresa

@Entity
public class Empresa {

	@Id
	@GeneratedValue
	private int id;
	private String nome;
//getters and setters
}

Usuarios

@Entity
public class Usuario {
	@Id
	private int id;
	private String usuario;
	private String senha;
	private Empresa empresa;
//getters and setters
}

criei as as classes como espelho das minhas duas tabelas no banco… gostaria de entender qual relacionamento usar… minha tabela EMPRESA nao tem vinculo com USUARIO, mas USUARIO tem vinculo com EMPRESA pelo ID .
Um USUARIO pode pertencer a varias EMPRESAS e varias EMPRESAS podem conter varios usuarios podendo repetir o mesmo entre elas.
1 - Entendi o relcacionamento como @ManytoMany ja que varios usuarios tem varias empresas… porem… como eu faria isso na classe??
2 - Eu precisaria mapear tambem na classe empresa ou somente na classe usuario, visto a tabela empresa nao tem vinculo com usuario???
3 - @manytomany geralmente é necessario uma tabela a parte para controlar as relaçoes… nesse caso nao necessito da tabela…

Conseguiram entender??

[quote=nesken]Aproveitando o topico para falar sobre @ManytoMany

Ex:
Vou postar minhas classes que estão exatamente iguais às minhas tabelas do meu banco de dados.

Empresa

@Entity
public class Empresa {

	@Id
	@GeneratedValue
	private int id;
	private String nome;
//getters and setters
}

Usuarios

@Entity
public class Usuario {
	@Id
	private int id;
	private String usuario;
	private String senha;
	private Empresa empresa;
//getters and setters
}

criei as as classes como espelho das minhas duas tabelas no banco… gostaria de entender qual relacionamento usar… minha tabela EMPRESA nao tem vinculo com USUARIO, mas USUARIO tem vinculo com EMPRESA pelo ID .
Um USUARIO pode pertencer a varias EMPRESAS e varias EMPRESAS podem conter varios usuarios podendo repetir o mesmo entre elas.
1 - Entendi o relcacionamento como @ManytoMany ja que varios usuarios tem varias empresas… porem… como eu faria isso na classe??
2 - Eu precisaria mapear tambem na classe empresa ou somente na classe usuario, visto a tabela empresa nao tem vinculo com usuario???
3 - @manytomany geralmente é necessario uma tabela a parte para controlar as relaçoes… nesse caso nao necessito da tabela…

Conseguiram entender?? [/quote]

Na classe Empresa

@ManyToMany
@JoinTable(name="nome_tabela_ternario_entre_EMPRESA_USUARIO", joinColumns={@JoinColumn(name="fk_empresa_tabela_ternaria")}, inverseJoinColumns={@JoinColumn(name="fk_usuario_tabela_ternaria")})
private List<Usuario> listaUsuaros    

Na classe Usuario

@ManyToMany(mappedBy="nome_variavel_lista_de_usuario_na_classe_Empresa")
private List<Empresa> listaEmpresas    

No banco vc deve ter
TB_EMPRESA, TB_USUARIO e uma TB_EMPRESA_USUARIO(tabela ternária) com uma fk para TB_EMPRESA e outra para TB_USUARIO.

Assim uma empresa terá vinculo com vários usuários e o usuário com várias empresas.

VOce está correto, obrigado pela resposta…