Persistencia com Hibernate

Opa Galera, blz ?

Eu estou desenvolvendo uma aplicação para aprender umas coisas novas e tal
e gostaria de saber se esse mapeamento que fiz está correto, ou se posso melhora-lo
em algum sentido ?

Agradeço des de já !

O relacionamento das tabelas é de Fornecedor para Material, entao 1 fornecedor tem N Materiais cadastrados.

Fornecedor:

package modelo;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.FetchType;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.OneToMany;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;
import modelo.Material;

@Entity(name="Fornecedor")
@Table(name="FORNECEDOR")
@SequenceGenerator(name = "seq_fornecedor", sequenceName = "seq_id_fornecedor")
public class Fornecedor implements Serializable {

    @Id
    @Column(name="CD_FORNECEDOR")
    @GeneratedValue(strategy = GenerationType.IDENTITY, generator = "seq_fornecedor")
    private int CD_FORNECEDOR;

    @OneToMany(fetch=FetchType.LAZY) //http://recurser.com/articles/2007/11/26/hibernate-onetomany-relationships/
    @Column(name="MATERIAL")
    private List<Material> MATERIAL = new ArrayList<Material>();


    @Column(name="NM_FORNECEDOR")
    private String NM_FORNECEDOR;

    @Column(name="CNPJ")
    private String CNPJ;

    public int getCD_FORNECEDOR() {
        return CD_FORNECEDOR;
    }

    public void setCD_FORNECEDOR(int CD_FORNECEDOR) {
        this.CD_FORNECEDOR = CD_FORNECEDOR;
    }

    public String getNM_FORNECEDOR() {
        return NM_FORNECEDOR;
    }

    public void setNM_FORNECEDOR(String NM_FORNECEDOR) {
        this.NM_FORNECEDOR = NM_FORNECEDOR;
    }


    public String getCNPJ() {
        return CNPJ;
    }


    public void setCNPJ(String CNPJ) {
        this.CNPJ = CNPJ;
    }


    public List<Material> getMATERIAL() {
        return MATERIAL;
    }

    public void setMATERIAL(List<Material> MATERIAL) {
        this.MATERIAL = MATERIAL;
    }

}

Material:

package modelo;

import java.io.Serializable;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.JoinColumn;
import javax.persistence.ManyToOne;
import javax.persistence.SequenceGenerator;
import javax.persistence.Table;

@Entity(name="Material")
@Table(name="MATERIAL")
@SequenceGenerator(name = "seq_material", sequenceName = "seq_id_material")
public class Material implements Serializable {

    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY, generator = "seq_material")
    @Column(name="CD_MATERIAL")
    private int CD_MATERIAL;

    //@Id ARRUMAR ISSO AQUI
    @Column(name="CD_FORNECEDOR")
    private int CD_FORNECEDOR;

    @Column(name="NM_MATERIAL")
    private String NM_MATERIAL;

    @Column(name="UNID_MEDIDA")
    private String UNID_MEDIDA;

    @Column(name="PESO")
    private float PESO;

    @Column(name="VALOR")
    private float VALOR;

    @ManyToOne
    @JoinColumn(name="MATERIAL")
    private Fornecedor fornecedor;

    public int getCD_MATERIAL() {
        return CD_MATERIAL;
    }

    public void setCD_MATERIAL(int CD_MATERIAL) {
        this.CD_MATERIAL = CD_MATERIAL;
    }

    public int getCD_FORNECEDOR() {
        return CD_FORNECEDOR;
    }

    public void setCD_FORNECEDOR(int CD_FORNECEDOR) {
        this.CD_FORNECEDOR = CD_FORNECEDOR;
    }

    public String getNM_MATERIAL() {
        return NM_MATERIAL;
    }

    public void setNM_MATERIAL(String NM_MATERIAL) {
        this.NM_MATERIAL = NM_MATERIAL;
    }

    public String getUNID_MEDIDA() {
        return UNID_MEDIDA;
    }

    public void setUNID_MEDIDA(String UNID_MEDIDA) {
        this.UNID_MEDIDA = UNID_MEDIDA;
    }

    public float getPESO() {
        return PESO;
    }

    public void setPESO(float PESO) {
        this.PESO = PESO;
    }

    public float getVALOR() {
        return VALOR;
    }

    public void setVALOR(float VALOR) {
        this.VALOR = VALOR;
    }

}

Uma coisa que aconteceu é que o Hibernate Cria uma Tabela chamada de “Fornecedor_Material”,
entretanto não coloca dados nela quado eu faço um insert e tals ! E ela não está respeitando a
validação de FK ! Posso inserir um material para um fornecedor que não Existe !

Outra coisa é que na classe de Material recebe a PK de Fornecedor (CD_FORNECEDOR), só que
os exemplos que eu achei na net eles criam um outro campo do tipo de Fornecedor para usar como
relacionamento ! Qual a melhor forma de tratar isso ??

Obrigado ! =]

Wakko, algumas observações:

  • Pense nas suas entidades como objetos e não como as tabelas do banco de dados. Por isso, na classe Material você não precisa colocar explicitamente o código do fornecedor (CD_FORNECEDOR), simplesmente colocando o objeto Fornecedor o hibernate já vai entender a associação. Dessa forma, no seu código Java, você encontra um Fornecedor simplesmente chamando
material.getFornecedor();
  • Outro detalhe é em relação as chaves. Não use tipos primitivos para chave primária, ao invés, use classes Wrappers, como Integer, Long, etc…

  • No caso da tabela Fornecedor_Material, ela é criada quando temos um relacionamento OneToMany unidirecional. No seu você está utilizando um relacionamento bidirecional e por isso essa tabela não está sendo populada. NO seu caso, no relacionamento OneToMany, faltou usar o atributo mappedBy para informar ao hibernate que é bidirecional. Exemplo na própria documentao do Hibernate: http://docs.jboss.org/hibernate/stable/annotations/reference/en/html_single/

  • Por último, uma prática que o pessoal tem usado é o nome da tabela (banco de dados) no plural e o objeto (aplicação) no singular.

Espero ter ajudado

MUITO boa explicação ! Obrigado !
uma dúvida, OK tenho que usar o mappedBy e colocaria ele no OneToMany da Classe !?
@OneToMany(mappedBy = “QUE NOME COLOCO AQUI ? é referencia ao que ?”, fetch=FetchType.LAZY)

Como ficaria ?
é poque eu não coloquei o atributo mappedBy que tambem ele não está validando a FK ?

Você deve colocar o nome do mapemanto da ManyToOne, no seu caso: mappedBy=“fornecedor”

Sobre o Hibernate validar as FK, ai você tem que utilizar outras annotations (de obrigatoriedade e etc).

blz no momento que vim aqui falar que tinha conseguindo
entender olhando o ERRO tu tinha me respondido !

Mais uma vez MUITO OBRIGADO !
Vou pesquisar quanto as anotations de Obrigatoriedade e tals !
Tem alguma dica ?