Hibernate Annotations - Mapeamento de herança

Olá PessoALL!
Estou brincando com annotations e estou com um probleminha.

Quero mapear a seguinte hierarquia:

–Pessoa
-----Funcionario extende Pessoa
---------Dentista extende Funcionario

O codigo de pessoa.hbm.xml seria algo assim:

<hibernate-mapping>   
    <class name="classes.Pessoa" table="pessoa">   
       <id name="id" type="integer">   
            <generator class="native"/>   
        </id>   
        <property name="nome" type="string"/>   
        <property name="cpf" type="string"/>   
           
        <joined-subclass name="classes.Funcionario" extends="classes.Pessoa" table="funcionario">   
            <key column="id"/>   
            <property name="matricula" type="integer"/>   
            <property name="horas" type="integer"/>   
               
            <joined-subclass name="classes.Dentista" extends="classes.Funcionario" table="dentista">   
                <key column="id"/>   
                <property name="cro" type="string"/>   
            </joined-subclass>
        </joined-subclass>
      </class>   
</hibernate-mapping>  

O que eu tentei fazer pra mapear com annotations foi o seguinte:

@Entity   
@Inheritance(strategy = InheritanceType.JOINED)   
@Table(name="pessoa")   
public class Pessoa implements Serializable{   
  
@Entity
@Table(name = "funcionario")
@PrimaryKeyJoinColumn(name = "pessoaId")
@Inheritance(strategy = InheritanceType.JOINED)
public class Funcionario extends Pessoa{   
  
@Entity
@Table(name = "dentista")
@PrimaryKeyJoinColumn(name = "funcionarioPessoaId")
public class Dentista extends Funcionario{

Ficou beleza até eu tentar fazer o seguinte:

session = HibernateUtil.getSessionFactory().openSession();
        String sql =  "SELECT * " +
                      "FROM funcionario fun, pessoa pes " +
                     "WHERE fun.nomedeusuario = '" + funcionario.getNomeDeUsuario() + "' " +
                       " AND fun.senha = '" + funcionario.getSenha() + "' " +
                       " AND fun.status = 'A'" +
                       " AND fun.pessoaId = pes.id";

        SQLQuery sqlQuery = session.createSQLQuery(sql);
        sqlQuery.addEntity(Funcionario.class);

        Funcionario out;
        out = (Funcionario) sqlQuery.uniqueResult();

Quando é chamado o método que executa o código acima, acontece o erro:

java.sql.SQLException: Column 'clazz_' not found.
	com.mysql.jdbc.SQLError.createSQLException(SQLError.java:1055)
	com.mysql.jdbc.SQLError.createSQLException(SQLError.java:956)
	com.mysql.jdbc.SQLError.createSQLException(SQLError.java:926)
	com.mysql.jdbc.ResultSetImpl.findColumn(ResultSetImpl.java:1093)
	com.mysql.jdbc.ResultSetImpl.getInt(ResultSetImpl.java:2734)
	org.hibernate.type.IntegerType.get(IntegerType.java:28)
	org.hibernate.type.NullableType.nullSafeGet(NullableType.java:163)
...

E ai!? Alguém sabe como me ajudar?

Bom, sou novato com Hibernate mas vou tentar te ajudar! :slight_smile:
Como você está utilizando a estratégia “JOINED”, talvez você deva utilizar a mesma @PrimaryKeyJoinColumn pra toda sua hierarquia.
Algo do tipo:

@Entity
@Table(name="pessoa")
@Inheritance(strategy=InheritanceType.JOINED)
public abstract class Pessoa implements Serializable{
//implementação
}
@Entity
@Table(name = "funcionario")
@PrimaryKeyJoinColumn(name="idpessoa")
@Inheritance(strategy=InheritanceType.JOINED)
public class Funcionario extends Pessoa{
//implementação
}
@Entity
@Table(name = "dentista")
@PrimaryKeyJoinColumn(name="idpessoa")
public class Dentista extends Funcionario{
//implementação
}

Comigo deu certo! Espero que tenha ajudado!
Abraços.

joncarv,

Tentei sua sugestão, mas não deu certo… :?
Tem mais alguma?
Como você fez?
Será que o problema está no método que faz a consulta?

Valeu d+!

Cara, eu não tinha reparado na sintaxe do SQL que você está montando e acho que talvez o problema possa estar nele.
O hibernate utiliza HQL que te possibilita montar sua queries navegando pelo seu modelo de classes (quem tem que se preocupar com o mapeamento OO/Relacional é ele e não você)! Não tem necessidade de você fazer o que você fez na consulta que está montando.
Você fez:

String sql =  "SELECT * " +  
                   "FROM funcionario fun, pessoa pes " +  
                   "WHERE fun.nomedeusuario = '" + funcionario.getNomeDeUsuario() + "' " +  
                   " AND fun.senha = '" + funcionario.getSenha() + "' " +  
                   " AND fun.status = 'A'" +  
                   " AND fun.pessoaId = pes.id";  

Quando na verdade, se você quer recuperar os dados do funcionário com base em alguns parâmetros, você deveria fazer:

Funcionario funcionario = (Funcionario) session.createQuery("SELECT f FROM Funcionario f WHERE f.nomedeusuario = :nome AND f.senha = :senha AND f.status = :status").setString("nome", "Nome do Funcionario").setString("senha", "Senha do Funcionario").setString("status", "A").uniqueResult();

Você não precisa fazer a comparação de ids entre Pessoa e Funcionario por que na verdade com o HQL você está navegando no modelo de classes, e no modelo de classes Funcionario é uma especialização de Pessoa, já contendo todas as suas propriedades.
O que está dentro do método createQuery não é SQL, é HQL, navegando dentro do modelo de classes!
Será que isso resolve seu problema? :slight_smile:

Veja esse exemplo aqui, é basicamente o que você quer fazer… aliás, estamos supondo que você está usando Hibernate… procede?

Exemplo: http://java-aap.blogspot.com/2006/04/hibernate-annotations-composite.html

joncarv,

Valeu cara! Você tinha razão!
O select que eu estava fazendo é que estava dando pala!
Na verdade postei aqui uma versão antiga do que realmente fazia… Quero dizer, o select que postei tinha um join que não preciso…

Eu tinha usado SQL bruto no codigo Java por facilidade de não precisar aprender HQL ou outra coisa… Só que, realmente fica feio pra caramba!
Misturar SQL com código Java não é uma boa opção…

Num fim das contas, usei criteria que, na minha opinião, deixa o código bem “mais bonito”…

        session = HibernateUtil.getSessionFactory().openSession();
        Criteria criteria = session.createCriteria(Funcionario.class);
        criteria.add(Restrictions.eq("nomeDeUsuario", funcionario.getNomeDeUsuario()));
        criteria.add(Restrictions.eq("senha", funcionario.getSenha()));
        criteria.add(Restrictions.eq("status", "A"));
        List resultado = criteria.list();

        Funcionario out = null;
        if (resultado.size() > 0) {
            out = (Funcionario) resultado.get(0);
        }

Mais uma vez, valeu pela ajuda! :smiley:

marcelo.bellissimo,

Valeu! Mas, o link que você postou não trata o que eu precisava. Ele fala sobre mapeamento de relacionamento N x N…

Que beleza, cara!
Precisando de mais alguma ajuda, é só falar! :slight_smile: