Ajuda com mapeamento usando Hib. Annotations

Olá povo, estou estudando sobre o Hibernate Annotation e estou com duas dúvidas:

Fiz as seguintes classes conforme a imagem abaixo.


1 - Está correta esta forma que estou pensando?

Seguindo uma apostila sobre annotation, resolvi usar essa herança com as tabelas no banco por classe concreta, ou seja, apesar da herança quero ter no banco somente duas tabelas, Aluno e Professor.
Minha dúvida é como fazer o mapeamento das classes Telefone e Endereco, sendo que elas estarão na mesma tabela do Aluno e Professor.
No banco eu tenho a seguintes tabelas:
aluno

DROP TABLE IF EXISTS `scs`.`aluno`;
CREATE TABLE  `scs`.`aluno` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `nome` varchar(50) NOT NULL,
  `email` varchar(50) default NULL,
  `identidade` varchar(15) default NULL,
  `cpf` int(10) unsigned default NULL,
  `datanascimento` date NOT NULL,
  `ativo` tinyint(1) NOT NULL,
  `observacao` blob,
  `foto` varchar(20) default NULL,
  `rua` varchar(50) default NULL,
  `numero` varchar(10) default NULL,
  `complemento` varchar(20) default NULL,
  `bairro` varchar(30) default NULL,
  `cidade` varchar(45) default NULL,
  `estado` varchar(20) default NULL,
  `cep` int(10) unsigned default NULL,
  `foneresidencial` varchar(14) default NULL,
  `fonecomercial` varchar(14) default NULL,
  `fonecelular` varchar(14) default NULL,
  `fonerecado` varchar(14) default NULL,
  `fax` varchar(14) default NULL,
  `nomedopai` varchar(50) default NULL,
  `nomedamae` varchar(50) default NULL,
  `nomedoresponsavel` varchar(50) default NULL,
  `parentescoresponsavel` varchar(20) default NULL,
  `cpfresponsavel` int(10) unsigned default NULL,
  `valormensalidade` double default NULL,
  `diapagamento` int(10) unsigned default NULL,
  `tipocobranca` varchar(20) default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

professor

DROP TABLE IF EXISTS `scs`.`professor`;
CREATE TABLE  `scs`.`professor` (
  `id` int(10) unsigned NOT NULL auto_increment,
  `nome` varchar(50) NOT NULL,
  `email` varchar(50) default NULL,
  `identidade` varchar(15) default NULL,
  `cpf` int(10) unsigned default NULL,
  `datanascimento` date NOT NULL,
  `ativo` tinyint(1) NOT NULL,
  `observacao` blob,
  `foto` varchar(20) default NULL,
  `endereco` varchar(50) default NULL,
  `numero` varchar(10) default NULL,
  `complemento` varchar(20) default NULL,
  `bairro` varchar(30) default NULL,
  `cidade` varchar(45) default NULL,
  `estado` varchar(20) default NULL,
  `cep` int(10) unsigned default NULL,
  `foneresidencial` varchar(14) default NULL,
  `fonecomercial` varchar(14) default NULL,
  `fonecelular` varchar(14) default NULL,
  `fonerecado` varchar(14) default NULL,
  `fax` varchar(14) default NULL,
  `qualificacao` varchar(30) default NULL,
  `especializacao` varchar(30) default NULL,
  PRIMARY KEY  (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=latin1;

No arquivo hibernate.cfg.html eu coloquei o seguinte mapeamento das classes:

            <!-- Mapeamento dos arquivos hbm -->
            <mapping class="scs.model.Aluno"/>
            <mapping class="scs.model.Professor"/>

Na minha classe Pessoa, ficou assim:

@MappedSuperclass
public class Pessoa {

    @Id
    @GeneratedValue(strategy = GenerationType.SEQUENCE)
    @Column(name="id")
    private int codigo;
    @Column(name="nome",length=50)
    private String nome;
    @Column(name="email",length=50)
    private String email;
    @Column(name="identidade",length=15)
    private String identidade;
    @Column(name="cpf")
    private String cpf;
    @Column(name="datanascimento")
    private String dataNascimento;
    @Column (name="ativo")
    private boolean ativo;
    @Column (name="foto")
    private String foto;
    @Column (name="observacao")
    private String observacao;

    private Endereco endereco;

    private Telefone telefone;

2 - Como eu faço o annotation de Endereco e Telefone declarado acima?

Removi as annotations desses dois atributos, pois já tentei de várias formas e não deu certo, a última usada foi OneToOne, mas dava mais erros ainda… hehe

Na classe Professor fiz da seguinte forma: (vou colocar somente ela que é menor que Aluno)

@Entity
@Table(name="professor", schema="scs")
@Inheritance(strategy = InheritanceType.TABLE_PER_CLASS)
public class Professor extends Pessoa{

    @Column (name="qualificacao")
    private String qualificacao;
    @Column (name="especializacao")
    private String especializacao;

    public Professor(){
        
    }

O Hibernate me retorna a seguinte exception:
[color=red]
Falha na criação da sessionFactory. Classe HibernateUtil
org.hibernate.MappingException: Could not determine type for: scs.model.Endereco, for columns: [org.hibernate.mapping.Column(endereco)]
Exception in thread “AWT-EventQueue-0” java.lang.ExceptionInInitializerError[/color]

Muito obrigado.

Acho que meu problema pode estar aqui também.

public class Endereco { @Column (name="rua") private String endereco; @Column (name="numero") private String numero; @Column (name="complemento") private String complemento; @Column (name="bairro") private String bairro; @Column (name="cidade") private String cidade; @Column (name="estado") private String estado; @Column (name="cep") private String cep;
Como que faço o annotation da classe Endereco?
Só fiz dos atributos, não declarei como uma entidade ainda, lembrando que ela não tem uma tabela no BD, está junto com o Aluno.

[]s
Alexander

Primeiro você precisa definir na classe pessoa a cardinalidade de Pessoa e Endereço. Tipo OneToMany, ManyToMany, ManyToOne. Um exemplo seria:


public class Pessoa{

    // UMA PESSOA POSSUI MUITOS ENDERECOS
    @OneToMany
    private Endereco endereco;  
   
    // UMA PESSOA POSSUI APENAS UM TELEFONE
    @OneToOne
    private Telefone telefone; 
}

isso é necessário, pois telefone e endereco nao sao campos espefícicos, mas sim relacionamento entre objetos(tabelas)

Thiago, já tentei desta forma, porém dá erro como se estivesse procurando no banco uma tabela chamada endereço, porém não tenho essa tabela no banco.

Tem alguma maneira de mapear um objeto que não tenha ID(Endereco) e que esteja com uma ligação OneToOne(Pessoa) sendo que os atributos dos dois objetos estejam sendo salvos em uma mesma tabela?

Fazendo dessa forma dá erro que não tem ID no Endereço.
[color=red]Falha na criação da sessionFactory. Classe HibernateUtil
org.hibernate.AnnotationException: No identifier specified for entity: scs.model.Endereco
Exception in thread “AWT-EventQueue-0” java.lang.ExceptionInInitializerError

Caused by: org.hibernate.AnnotationException: No identifier specified for entity: scs.model.Endereco[/color]

[]s
Alexander

vou dar minha opinião, se continuar querendo fazer, conforme seu esquema depois da minha opinião, posso te dar um help…

vamos la… já pensou na possibilidade, que um Professor e um Aluno em essencia são uma Pessoa, porem que ser Aluno não impede em nada de vc ser um professor ??? … e vice-versa ?? …

cuidado com herença, a herança deve ser usada, quando realmente é visto um polimorfismo …

veja outra analise do seu problema…

Pessoa 1 tem 0 … N Endereco (se vc kizer pode ser de 1 - 0…1)
Pessoa 1 tem 0 … N Telefone (se vc kizer pode ser de 1 - 0…1)

Aqui vem o problema, uma Pessoa pode ser um Aluno, porem uma Pessoa pode ser um Professor, mas veja bem, um pessoa pode ser ate os 2 ao mesmo tempo…

Que tal assim ??

Pessoa 1 tem 0 … 1 Aluno
Pessoa 1 tem 0 … 1 Professor

ai vem a duvida, como saber c é realmente um professor ou um aluno ??

[code]public class Pessoa implements Serializable {

//… outra propriedades

@OneToOne(mappedBy=“pessoa”) //ou seja, mapeado pela propriedade Aluno.pessoa
private Aluno aluno;
@OneToOne(mappedBy=“pessoa”) //ou seja, mapeado pela propriedade Professor.pessoa
private Professor professor;

//…

/**
* Retorna informações detalhadas, se houver, dos atributos de aluno desta pessoa
* @return null se não for aluno, ou um objeto Aluno com informações especifica deste Aluno.
/
public Aluno getAluno() {
return aluno;
}
/
*
* Indica se esta pessoa também é um aluno.
* @return true caso a pessoa seja também um aluno, false caso contrário.
*/
public boolean isAluno() {
return getAluno() == null;
}

/**
* Retorna informações detalhadas, se houver, dos atributos de professor desta pessoa
* @return null se não for professor, ou um objeto Professor com informações especifica deste Professor.
/
public Professor getProfessor() {
return professor;
}
/
*
* Indica se esta pessoa também é um professor.
* @return true caso a pessoa seja também um professor, false caso contrário.
*/
public boolean isProfessor() {
return getProfessor() == null;
}

//… restante
}[/code]

Assim acho que vc diminui o numero de tabelas, e podera continuar seu projeto orieantado OO, sem gasta Herença com isso

pense nisso… e se não kizer fazer assim, da pra fazer com herença tb, mas acho q é um disperdicio, imagina vc começar a ter q acrescentar + coisa nesse seu projeto, como funcionario, e outras coisas… e assim vc acaba se perdendo com tanta herança…

boa sorte

[code]public class Aluno implements Serializable {
@OneToOne
private Pessoa pessoa;

//… outros atributos de aluno…

public Pessoa getPessoa() {
return pessoa;
}
}[/code]

[code]public class Professor implements Serializable {
@OneToOne
private Pessoa pessoa;

//… outros atributos de aluno…

public Pessoa getPessoa() {
return pessoa;
}
}[/code]

segue um link interessante.
Lá mostra vários casos que podem ser mapeados utilizando anotação.