2 classes salvando em uma tabela. Herança com Hibernate

18 respostas
L

Ola,

Tem uma classe Pessoa, e dois classe que quero implentar para herdar de Pessoa, são elas, Clientes e Fornecedores.

Utilizando simplesmente assim: public class Cliente extends Pessoa implements Serializable

Da erro quando compila

Estou utilizando o Hibernate

o erro é :

Exception in thread "main" javax.persistence.PersistenceException: [PersistenceUnit: ControleFinanceiroPU] Unable to configure EntityManagerFactory at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:265) at org.hibernate.ejb.HibernatePersistence.createEntityManagerFactory(HibernatePersistence.java:125) at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:51) at javax.persistence.Persistence.createEntityManagerFactory(Persistence.java:33) at controlefinanceiro.hibernate.Jpa.ClienteJpaController.<init>(ClienteJpaController.java:24) at controlefinanceiro.Main.main(Main.java:25) Caused by: org.hibernate.AnnotationException: Unable to define/override @Id(s) on a subclass: controlefinanceiro.Cliente at org.hibernate.cfg.AnnotationBinder.bindId(AnnotationBinder.java:1867) at org.hibernate.cfg.AnnotationBinder.processElementAnnotations(AnnotationBinder.java:1281) at org.hibernate.cfg.AnnotationBinder.bindClass(AnnotationBinder.java:754) at org.hibernate.cfg.AnnotationConfiguration.processArtifactsOfType(AnnotationConfiguration.java:534) at org.hibernate.cfg.AnnotationConfiguration.secondPassCompile(AnnotationConfiguration.java:286) at org.hibernate.cfg.Configuration.buildMappings(Configuration.java:1115) at org.hibernate.ejb.Ejb3Configuration.buildMappings(Ejb3Configuration.java:1225) at org.hibernate.ejb.EventListenerConfigurator.configure(EventListenerConfigurator.java:159) at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:854) at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:191) at org.hibernate.ejb.Ejb3Configuration.configure(Ejb3Configuration.java:253) ... 5 more Java Result: 1 CONSTRUÍDO COM SUCESSO (tempo total: 1 segundo)

Se puderem, me ajudar, Obrigado.

18 Respostas

P

Se vc postar o codigo fonte das entidades fica mais fácil, agora pelo erro que ta aí, parece que vc ta definindo atributos duplicados na entidade mãe e nas filas, no caso o Id.

L

Classe Pai.

package controlefinanceiro;

import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

/**
 *
 * @author Raphael
 */
@Entity
public abstract class Pessoa implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String sNomeRazao;
    private String sEndereco;

    public String getSEndereco() {
        return sEndereco;
    }

    public void setSEndereco(String sEndereco) {
        this.sEndereco = sEndereco;
    }

    public String getSNomeRazao() {
        return sNomeRazao;
    }

    public void setSNomeRazao(String sNomeRazao) {
        this.sNomeRazao = sNomeRazao;
    }

    public Long getId() {
        return id;
    }

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

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (id != null ? id.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Pessoa)) {
            return false;
        }
        Pessoa other = (Pessoa) object;
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "controlefinanceiro.Pessoa[id=" + id + "]";
    }

}

Classe Filha, tanto a cliente quanto a forncedor, estao da forma abaixo...

package controlefinanceiro;

import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;

/**
 *
 * @author Raphael
 */
@Entity
public class Cliente implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String sCpf;
    private String nome;

    public String getNome() {
        return nome;
    }

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

    public String getSCpf() {
        return sCpf;
    }

    public void setSCpf(String sCpf) {
        this.sCpf = sCpf;
    }

    public Long getId() {
        return id;
    }

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

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (id != null ? id.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Cliente)) {
            return false;
        }
        Cliente other = (Cliente) object;
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "controlefinanceiro.Cliente[id=" + id + "]";
    }
}

Eu quero tanto Cliente, quanto Fornecedor, gravar na tabela pessoa...

Obrigado

R

Cara, eu acredito que voce vai precisar mapear uma estratégia pra essa herança, @Inheritance

dá uma olhada no primeiro pdf que aparece nessa busca na parte de heranças:

http://www.google.com.br/#hl=pt-BR&source=hp&q=hibernate+com+anotações&aq=0&aqi=g1&aql=&oq=hibernate+com+ano&gs_rfai=&fp=2fdbb4db882bc1dd

L

Opa, comecei a dar uma lida e aparentemente vai me atender…acho que não estava sabendo como “procurar” no google. Valeu cara…

F

Aparentemente o erro corresponde aos campos @Id, ele diz que sua classe filha não pode sobreescrever o @Id da classe pai.

L

é, pelo que estou entendendo é isso mesmo. O que na verdade eu quero fazer, é ter uma tabela e 2 classes por exemplo, armazendo nesta unica tabela, apenas com atributos diferentes para cada classe…

G

Cara se vc não pretende criar uma tabela Pessoa, coloque uma anotação do tipo @MappedSuperClass na classe pessoa, e retire o override do atributo de id…

L

O que eu quero é, criar uma Tabela Pessoa, e ter a classe Fornecedor e cliente Salvando na tabela Pessoa.
Porem, a classe cliente terá o atributo cpf, por exemplo e a fornecedor cnpj… Onde a classe Cliente e Fornecedor vao herdar os atributos em comuns da classe Pessoa. E ao cadastrar cliente e/ou fornecedor, quero salvar na tabela pessoa…entendeu?

G

Humm, entendi. Não sei se isso vai funcionar mas tente colocar a anotação @Table(name=“nome_tabela_pessoa”) nas 3 classes. Mas por causa desses 2 atributos diferentes acho é capaz do hibernate se perder…

R

Se voce pretende com que seu banco crie uma tabela para cada classe sua, use o @Inheritance JOINED

sempre que mandar salvar um filho automaticamente os atributos referentes a classe mae é salvo :wink:

Sua mãe :

@Inheritance(strategy= InheritanceType.JOINED) public class CLASSE_MAE implements Serializable {
Filhas:

@Entity
@Table(name = "NOME DA TABELA")
@PrimaryKeyJoinColumn(name = "FILHA_ID")
@ForeignKey(name = "FILHA_MAE_FK")
public class CLASSE_FILHA extends CLASSE_MAE  implements Serializable {

lembrando que suas filhas nao terao um atributo id , sempre o id da filha será a fk para mae e isso é controlado pelo propio framework.

L

Oláo, o que eu quero é varios objetos salvando na mesma classe.

Classe Filha:

package utilizandointerface;

import java.io.Serializable;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.persistence.Table;
import org.hibernate.annotations.ForeignKey;


@Entity
@Table(name= "cliente")
@PrimaryKeyJoinColumn(name = "id")
@ForeignKey(name="Id_pessoa_fk")
public class  Cliente extends Pessoa implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private int tipo;

    public int getTipo() {
        return tipo;
    }

    public void setTipo(int tipo) {
        this.tipo = tipo;
    }

    public Long getId() {
        return id;
    }

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

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (id != null ? id.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Cliente)) {
            return false;
        }
        Cliente other = (Cliente) object;
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "utilizandointerface.Cliente[id=" + id + "]";
    }

}

Classe Pai:

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package utilizandointerface;

import java.io.Serializable;
import java.util.Date;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.Inheritance;
import javax.persistence.InheritanceType;

/**
 *
 * @author Sourcesafe
 */
@Entity
@Inheritance(strategy= InheritanceType.JOINED)
public class Pessoa implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String nome;
    private Long cpf;
    private Long cnpj;



    public Long getId() {
        return id;
    }

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

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (id != null ? id.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the id fields are not set
        if (!(object instanceof Pessoa)) {
            return false;
        }
        Pessoa other = (Pessoa) object;
        if ((this.id == null && other.id != null) || (this.id != null && !this.id.equals(other.id))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "utilizandointerface.Pessoa[id=" + id + "]";
    }

}

Ai, eu vou ter uma outra classe filha que vai herdar da pai, por exemplo Fornecedor. Com um outro atributo que seja comun só dele.. Mas quero salvar todos objetos que herdarem da classe pai, na tabela da classe pai, no exemplo classe Pessoa.

Resumindo: Salvar os objetos fornecedor e cliente, na tabela pessoa, que é minha classe pai.

Obrigado.

R

se voce usar Joined nao precisa do atributo id na classe filha, já é definido atraves da anotação @PrimaryKeyJoinColumn(name = “id”).

Mas, usando Joined, vai criar uma tabela para cada classe no seu banco, que vao se relacionar atravez da pk e fk, se voce pensa em poliformismo, fuja dessa herança.

se o que voce quer é que se banco fique com uma unica tabela contendo todos os atributos das suas classes que estao na herança, voce vai ter que mapear de outra forma , single_table , vai criar apenas uma tabela no banco e voce distingue suas classes através do uso de uma descriminator column. nunca usei dessa forma, mas na apostila que passei tá explicando certinho como fazer :wink:

att.

L

Olá,
Entendi, mas como faço para ter a classe filha sem a Id, pq quando crio a classe entidade, ele ja cria automaticamente a Id…eu removi, mas nao funfou.

valeu

L

Ricardo, uma duvida, nesse caso que estamos discutindo…A melhor forma é eu ter 2 classes, salvando em uma tabela, ou 1 tabela para cada classe? Isso depende do tamanho da aplicação? Qual sua opinao sobre isso?

valeu

R

Olha lucas , nao tenho conhecimento afundo pra postar uma opniao, tirando pela questao do poliformismo, nao sei falar o que muda em cada tipo de heranca a nao ser pela forma fisica com que o banco eh gerado. Vamos ficar no aguardo de alguem que tenha conhecimento pra tirar esta duvida.

em dois projetos que fiz utilizei Joined, simpelsmente pela estrutura relacional com que o banco eh gerado.

quanto a nao conseguir dexar sem id … poste suas classe pra dar uma olhada.

att.

L

Olá,

Fiz utilizando o PrimaryKeyJoinColumn, mas nao adiantou.

Classe Filha

@Entity
@Table(name= "cliente")
@PrimaryKeyJoinColumn(name = "id_pessoa")
public class Cliente extends Pessoa implements Serializable {
    private static final long serialVersionUID = 1L;
    private Long id;


    @Override
    public Long getId() {
        return id;
    }

    @Override
    public void setId(Long id) {
        this.id = id;
    }

Classe Pai

@Entity
@Table(name = "pessoa")
@Inheritance(strategy= InheritanceType.JOINED)
public class Pessoa implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.AUTO)
    private Long id;
    private String nome;
    private Long cpf;
    private Long cnpj;
    private int tipo;

    public Long getCnpj() {
        return cnpj;
    }

    public void setCnpj(Long cnpj) {
        this.cnpj = cnpj;
    }

Ai, o que esta rolando agora é, quando crio o objeto Cliente no main e tento dar obj.setCnpj, fica pedido para cirar este metodo na classe cliente...sendo que este metodo é da classe pai. Tipo, nao tem necessidade de criar os metodos existentes na classe pai, cria-los na classe filha né?

Quanto a estrutura das classes, como ficaria entao, só criando o relacionamento entre as tabelas, considerando agora, que vou criar uma tabela para cada classe, mas que vou relaciona-las com FK...

value...

R

use long , não Long.. L minusculo.

testei aqui, da certinho :

import javax.persistence.*;
import org.hibernate.*;
import java.io.*;

@Entity   
@Table(name = "pessoa")   
@Inheritance(strategy= InheritanceType.JOINED)   
public class Pessoa implements Serializable {   
 
    @Id   
    @GeneratedValue(strategy = GenerationType.AUTO)   
    private long id;   
    private String nome;   
    private long cpf;   
    private long cnpj;   
    private int tipo;
	public long getId() {
		return id;
	}
	public void setId(long id) {
		this.id = id;
	}
	public String getNome() {
		return nome;
	}
	public void setNome(String nome) {
		this.nome = nome;
	}
	public long getCpf() {
		return cpf;
	}
	public void setCpf(long cpf) {
		this.cpf = cpf;
	}
	public long getCnpj() {
		return cnpj;
	}
	public void setCnpj(long cnpj) {
		this.cnpj = cnpj;
	}
	public int getTipo() {
		return tipo;
	}
	public void setTipo(int tipo) {
		this.tipo = tipo;
	}
	
    
}
import javax.persistence.*;
import org.hibernate.*;
import java.io.*;


@Entity   
@Table(name= "cliente")   
@PrimaryKeyJoinColumn(name = "id_pessoa")   
public class Cliente extends Pessoa implements Serializable {   
  
}
public void teste(){
		 Cliente obClient = new Cliente();
		 obClient.setTipo(0);
		 obClient.setNome("nome");
	     obClient.setCnpj(445525522);
		 
		 
	  }

att.

L

Fala Ricardo, deu certo cara. Criou a tabela pessoa com os atributos principais, a tabela fornecedor somente com o campo ‘id_pessoa’ e a tabela cliente somente com o campo ‘id_pessoa’… Em partes deu certo…

agora vou ver se consigo, na tabela Pessoa, eu ter a id_cliente e a id_fornecedor, assim fico com 1 tabela só…

valeu cara

Criado 14 de agosto de 2010
Ultima resposta 25 de ago. de 2010
Respostas 18
Participantes 5