Join no HQL não funciona

Esse meu join me retorna erro

Query query = getEntityManager().createQuery(" from Escola esc ,Matricula mat, Professor prof " + " where mat.idescola = esc.idescola and mat.idprofessor = prof.idprofessor and" + " mat.situacao = 'A' and idprofessor = 2 order by esc.nome");

O erro abaixo

[quote]exception

javax.servlet.ServletException: org.hibernate.QueryException: could not resolve property: idprofessor of: br.com.mosaicodigital.modelo.Professor [ from br.com.mosaicodigital.modelo.Escola esc ,br.com.mosaicodigital.modelo.Matricula mat, br.com.mosaicodigital.modelo.Professor prof where mat.idescola = esc.idescola and mat.idprofessor = prof.idprofessor and mat.situacao = ‘A’ and idprofessor = 2 order by esc.nome]
root cause

java.lang.IllegalArgumentException: org.hibernate.QueryException: could not resolve property: idprofessor of: br.com.mosaicodigital.modelo.Professor [ from br.com.mosaicodigital.modelo.Escola esc ,br.com.mosaicodigital.modelo.Matricula mat, br.com.mosaicodigital.modelo.Professor prof where mat.idescola = esc.idescola and mat.idprofessor = prof.idprofessor and mat.situacao = ‘A’ and idprofessor = 2 order by esc.nome]
root cause

org.hibernate.QueryException: could not resolve property: idprofessor of: br.com.mosaicodigital.modelo.Professor [ from br.com.mosaicodigital.modelo.Escola esc ,br.com.mosaicodigital.modelo.Matricula mat, br.com.mosaicodigital.modelo.Professor prof where mat.idescola = esc.idescola and mat.idprofessor = prof.idprofessor and mat.situacao = ‘A’ and idprofessor = 2 order by esc.nome]
note The full stack traces of the exception and its root causes are available in the GlassFish Server Open Source Edition 3.0.1 logs.
[/quote]

existe um atributo idprofessor (exatamente escrito assim) na classe professor ?

could not resolve property: idprofessor of: br.com.mosaicodigital.modelo.Professor

Refiz o etributo, java é Case Sensitive, mas como HQL não o é, achei que ele não se importaria com isso, mas se importou sim. Bem, fiz as correções e agora deu um novo erro. Ele diz de uma coluna no banco que não existe. Procurei onde por ventura eu faço menção a ela e não encontrei nada. Para não ficar postando todo o erro(muito grande) postei apenas,acho, o essencial.

javax.servlet.ServletException: org.hibernate.exception.SQLGrammarException: could not execute query org.postgresql.util.PSQLException: ERRO: coluna professor2_.tipopessoa não existe Posição: 662

Esse é meu select em HQL.

[code]public List<Escola> findAll() {

	Query query =  getEntityManager().createQuery(" from Escola esc ,Matricula mat, Professor prof " +
			                                      " where mat.idescola = esc.idescola and mat.idprofessor = prof.idprofessor and" +
			                                      " mat.situacao = 'A' and mat.idprofessor = 2 order by esc.nome");    
         return (List&lt;Escola&gt;) query.getResultList();

}[/code]

Resolvi o tipopessoa. Era um ENUM que apontava para tipopessoa e na realidade o nome dessa coluna era tipo. Corrigi e agora o erro mudou para:

org.postgresql.util.PSQLException: ERRO: coluna professor2_.idprofessor não existe Posição: 692

Realmente eu não estou entendendo mais nada. A coluna idprofessor ela existe em várias entidades, várias mesmo,
pois ele é o cara principal no projeto, o professor.

se testo sem o join funciona, mas com ele(tem que ser com ele) não funciona.

Fiz um join e tá dando um erro de que uma coluna(dtype) não existe. Tentei saber de omnde ele tá lendo isso e não achei. Abaixo os códigos:
Meu Join

Query query = getEntityManager().createQuery("select esc from Escola esc ,Matricula mat, Professor prof " + " where mat.idescola = esc.idescola and mat.idprofessor = prof.idprofessor and" + " mat.situacao = 'A' and mat.idprofessor = 2 order by esc.nome"); return (List&lt;Escola&gt;) query.getResultList();
Meu erro:

org.postgresql.util.PSQLException: ERRO: coluna professor2_.dtype não existe Posição: 218

Se retirar o join funciona.

Achei estranho o log gerado. Veja como ficou o log do hibernate

INFO: Hibernate: select escola0_.idescola as idescola2_, escola0_.nome as nome2_, escola0_.telefone as telefone2_, escola0_.fax as fax2_, escola0_.email as email2_ from escola escola0_, matricula matricula1_, pessoa professor2_ where professor2_.DTYPE='Professor' and matricula1_.idprofessor=professor2_.idprofessor and matricula1_.idescola=escola0_.idescola and matricula1_.situacao='A' and idprofessor=1 order by escola0_.nome

e veja como é meu Join

Query query = getEntityManager().createQuery("select esc from Escola esc ,Matricula mat,Professor prof" + " where mat.idprofessor = prof.idprofessor and mat.idescola = esc.idescola" + " and mat.situacao = 'A' and idprofessor = 1 order by esc.nome"); return (List&lt;Escola&gt;) query.getResultList();

[quote=pjava]Achei estranho o log gerado. Veja como ficou o log do hibernate

[code]
e veja como é meu Join

Query query = getEntityManager().createQuery("select esc from Escola esc ,Matricula mat,Professor prof" + " where mat.idprofessor = prof.idprofessor and mat.idescola = esc.idescola" + " and mat.situacao = 'A' and idprofessor = 1 order by esc.nome"); return (List&lt;Escola&gt;) query.getResultList();[/quote]

na parte idprofessor = 1 especifique de onde que vem prof.idprofessor = 1, pois tem a mesmo atributo na classe matricula e na classe professor

Cara, fiz a alteração(realmente era um erro grave, de falta de atenção) e continua a dar o mesmo erro.

Estranho, deve ter alguma outra mensagem no log, poste o log gerado agora.

coloquei essa linha no meu persistence e agora ele não dá mais erro, mas não carrega nada na lista. O select vem vazio.

&lt;property name="hibernate.hbm2ddl.auto" value="update" /&gt;

Ele gerou idprofessor. Professor é que deveria gerar idpessoa.

Essa linha que eu coloquei no persistence, ele simplesmente adicionou em pessoa os campos de Professor, ficando professor uma tabela só e não é isso que gostaríamos e ainda criou um campo Pessoa do tipo bytea. Não sei o que é isso.

coloque suas classes que você utiliza para fazer o seu SQL

[code]@Entity
@Table(name=“professor”)
@SequenceGenerator(name=“seq_professor”, sequenceName=“professor_idprofessor_seq”, allocationSize=1)
public class Professor extends Pessoa implements Serializable {

private static final long serialVersionUID = 8683441216699864995L;

@Column(name="idprofessor")
private int idprofessor;
@Column(name="foto")
private String foto;
private Pessoa pessoa;

public int getIdProfessor() {
	return idprofessor;
}

public void setIdProfessor(int idProfessor) {
	this.idprofessor = idProfessor;
}

public String getFoto() {
	return foto;
}

public void setFoto(String foto) {
	this.foto = foto;
}

public Pessoa getPessoa() {
	return pessoa;
}

public void setPessoa(Pessoa pessoa) {
	this.pessoa = pessoa;
}

@Override
public int hashCode() {
	final int prime = 31;
	int result = super.hashCode();
	result = prime * result + ((foto == null) ? 0 : foto.hashCode());
	result = prime * result + idprofessor;
	result = prime * result + ((pessoa == null) ? 0 : pessoa.hashCode());
	return result;
}

@Override
public boolean equals(Object obj) {
	if (this == obj)
		return true;
	if (!super.equals(obj))
		return false;
	if (getClass() != obj.getClass())
		return false;
	Professor other = (Professor) obj;
	if (foto == null) {
		if (other.foto != null)
			return false;
	} else if (!foto.equals(other.foto))
		return false;
	if (idprofessor != other.idprofessor)
		return false;
	if (pessoa == null) {
		if (other.pessoa != null)
			return false;
	} else if (!pessoa.equals(other.pessoa))
		return false;
	return true;
}	

}[/code]

[code]@Entity
@Table(name=“matricula”)
@SequenceGenerator(name=“seq_matricula”, sequenceName=“matricula_idmatricula_seq”, allocationSize=1)
public class Matricula implements Serializable{

private static final long serialVersionUID = 0L;

@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="seq_matricula")	
@Column(name="idmatricula")	
private Integer idmatricula;
@Column(name="idprofessor")	
private Integer idprofessor;
@Column(name="idescola")	
private Integer idescola;
@Temporal(TemporalType.DATE)
private Calendar dtmatricula;
@Column(name="situacao")
private String situacao;	

public Matricula(){	
}

public Matricula(Integer idmatricula,Integer idprofessor, Integer idescola,java.util.Calendar dtmatricula,String situacao){
	this.idmatricula = idmatricula;
	this.idprofessor = idprofessor;
	this.idescola    = idescola;
	this.dtmatricula = dtmatricula;
	this.situacao    = situacao;		
}

public long getIdmatricula() {
	return idmatricula;
}
public void setIdmatricula(Integer idmatricula) {
	this.idmatricula = idmatricula;
}
public long getIdprofessor() {
	return idprofessor;
}
public void setIdprofessor(Integer idprofessor) {
	this.idprofessor = idprofessor;
}
public long getIdescola() {
	return idescola;
}
public void setIdescola(Integer idescola) {
	this.idescola = idescola;
}
public java.util.Calendar getDtmatricula() {
	return dtmatricula;
}
public void setDtmatricula(java.util.Calendar dtmatricula) {
	this.dtmatricula = dtmatricula;
}
public String getSituacao() {
	return situacao;
}
public void setSituacao(String situacao) {
	this.situacao = situacao;
}
public static long getSerialversionuid() {
	return serialVersionUID;
}

@Override
public boolean equals(Object obj) {
	if (this == obj)
		return true;
	if (obj == null)
		return false;
	if (getClass() != obj.getClass())
		return false;
	Matricula other = (Matricula) obj;
	if (idmatricula == null) {
		if (other.idmatricula != null)
			return false;
	} else if (!idmatricula.equals(other.idmatricula))
		return false;
	return true;
}

}[/code]

[code]@Entity
@Table(name=“pessoa”)
@SequenceGenerator(name=“seq_pessoa”, sequenceName=“pessoa_idpessoa_seq”, allocationSize=1)
public class Pessoa implements Serializable {

private static final long serialVersionUID = -7427597435054021998L;

@Id
@GeneratedValue(strategy=GenerationType.SEQUENCE, generator="seq_pessoa")
@Column(name="idPessoa")
private int idPessoa;
@Column(name="nome")
private String nome;
@Column(name="sobrenome")
private String sobrenome;
@Column(name="sexo")
private EnumSexo sexo;
@Column(name="cpf")
private String cpf;
@Column(name="telefoneComercial")
private String telefoneComercial;
@Column(name="telefoneResidencial")
private String telefoneResidencial;
@Column(name="email")
private String email;
@Column(name="tipo")
private EnumTipoPessoa tipo;

public int getIdPessoa() {
	return idPessoa;
}

public void setIdPessoa(int idPessoa) {
	this.idPessoa = idPessoa;
}

public String getNome() {
	return nome;
}

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

public String getSobrenome() {
	return sobrenome;
}

public void setSobrenome(String sobrenome) {
	this.sobrenome = sobrenome;
}

public EnumSexo getSexo() {
	return sexo;
}

public void setSexo(EnumSexo sexo) {
	this.sexo = sexo;
}

public String getCpf() {
	return cpf;
}

public void setCpf(String cpf) {
	this.cpf = cpf;
}

public String getTelefoneComercial() {
	return telefoneComercial;
}

public void setTelefoneComercial(String telefoneComercial) {
	this.telefoneComercial = telefoneComercial;
}

public String getTelefoneResidencial() {
	return telefoneResidencial;
}

public void setTelefoneResidencial(String telefoneResidencial) {
	this.telefoneResidencial = telefoneResidencial;
}

public String getEmail() {
	return email;
}

public void setEmail(String email) {
	this.email = email;
}


public EnumTipoPessoa getTipoPessoa() {
	return tipo;
}

public void setTipoPessoa(EnumTipoPessoa tipo) {
	this.tipo = tipo;
}

public static long getSerialversionuid() {
	return serialVersionUID;
}

@Override
public int hashCode() {
	final int prime = 31;
	int result = 1;
	result = prime * result + ((cpf == null) ? 0 : cpf.hashCode());
	result = prime * result + ((email == null) ? 0 : email.hashCode());
	result = prime * result + idPessoa;
	result = prime * result + ((nome == null) ? 0 : nome.hashCode());
	result = prime * result + ((sexo == null) ? 0 : sexo.hashCode());
	result = prime * result
			+ ((sobrenome == null) ? 0 : sobrenome.hashCode());
	result = prime
			* result
			+ ((telefoneComercial == null) ? 0 : telefoneComercial
					.hashCode());
	result = prime
			* result
			+ ((telefoneResidencial == null) ? 0 : telefoneResidencial
					.hashCode());
	result = prime * result
			+ ((tipo == null) ? 0 : tipo.hashCode());
	return result;
}

@Override
public boolean equals(Object obj) {
	if (this == obj)
		return true;
	if (obj == null)
		return false;
	if (getClass() != obj.getClass())
		return false;
	Pessoa other = (Pessoa) obj;
	if (cpf == null) {
		if (other.cpf != null)
			return false;
	} else if (!cpf.equals(other.cpf))
		return false;
	if (email == null) {
		if (other.email != null)
			return false;
	} else if (!email.equals(other.email))
		return false;
	if (idPessoa != other.idPessoa)
		return false;
	if (nome == null) {
		if (other.nome != null)
			return false;
	} else if (!nome.equals(other.nome))
		return false;
	if (sexo != other.sexo)
		return false;
	if (sobrenome == null) {
		if (other.sobrenome != null)
			return false;
	} else if (!sobrenome.equals(other.sobrenome))
		return false;
	if (telefoneComercial == null) {
		if (other.telefoneComercial != null)
			return false;
	} else if (!telefoneComercial.equals(other.telefoneComercial))
		return false;
	if (telefoneResidencial == null) {
		if (other.telefoneResidencial != null)
			return false;
	} else if (!telefoneResidencial.equals(other.telefoneResidencial))
		return false;
	if (tipo != other.tipo)
		return false;
	return true;
}	

}[/code]

[code]public class ListaEscola {
private List<Escola> escola;
private EntityManager em;

public List&lt;Escola&gt; getEscola() {
	return escola;
}
public void setEscola(List&lt;Escola&gt; escola) {
	this.escola = escola;
}	
public EntityManager getEm() {  
    return em;  
}  
public void setEm(EntityManager em) {  
    this.em = em;  
}  	
protected EntityManager getEntityManager() 
{     
	if (this.em == null)  {
        this.em = EntityManagerFactorySingleton.getInstance().createEntityManager();
    }// throw new IllegalStateException("Erro");      
    return this.em; 
}	
/*public Session getSession() {
    EntityManager entityManager;
	return ((Session)entityManager.getDelegate());
}
 public final Criteria createCriteriaExample(Entity example) {
    Criteria executableCriteria = getSession().createCriteria(example.getClass());
   
    return executableCriteria;
}*/
public List&lt;Escola&gt; findAll() { 
	        
	Query query =  getEntityManager().createQuery("select esc from Escola esc ,Matricula mat,Professor prof" +
			                                      " where mat.idprofessor = prof.idprofessor and mat.idescola = esc.idescola" +
			                                      " and mat.situacao = 'A' and prof.idprofessor = 1 order by esc.nome");    
         return (List&lt;Escola&gt;) query.getResultList();

}	

}[/code]

[code]@ManagedBean(name=“MostraEsc”)
@ViewScoped
public class MostraEscolaAtiva implements Serializable{
private List<Escola> escolas;
private String nm = “Teste”;

public String getNm() {
	return nm;
}

public void setNm(String nm) {
	this.nm = nm;
}

public void handleToggle(ToggleEvent event) {  
    FacesMessage msg = new FacesMessage(FacesMessage.SEVERITY_INFO, "Fieldset Toggled", "Visibility:" + event.getVisibility());    
    FacesContext.getCurrentInstance().addMessage(null, msg);  
}  	

public List&lt;Escola&gt; getEscolas() {
	if(escolas == null){    
        escolas = new ListaEscola().findAll();
        	
    }   
        return escolas;
}

public void setEscolas(List&lt;Escola&gt; escolas) {
	this.escolas = escolas;
}

}[/code]

[code]<?xml version="1.0" encoding="UTF-8"?>

<persistence>
<persistence-unit name=“puMosaicoDigital”>
<properties>
<property name=“hibernate.archive.autodetection” value=“class, hbm” />

		&lt;property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" /&gt;
		&lt;property name="hibernate.connection.driver_class" value="org.postgresql.Driver" /&gt;
		&lt;property name="hibernate.connection.url" value="jdbc:postgresql://localhost:5435/Mosaico" /&gt;
		&lt;property name="hibernate.connection.username" value="postgres" /&gt;
		&lt;property name="hibernate.connection.password" value="eguru" /&gt;
		&lt;property name="hibernate.show_sql" value="true" /&gt;
		&lt;property name="hibernate.format_sql" value="true" /&gt;
		&lt;property name="hibernate.hbm2ddl.auto" value="update" /&gt;
	&lt;/properties&gt;
&lt;/persistence-unit&gt;

</persistence>[/code]
ACHO QUE É ISSO. O PERSISTENCE É QUE A DÚVIDA. ACHO QUE É MAPEAMENTO, MAS NÃO SEI COMO RESOLVER.

faltou você mapear as suas classes no na sua unidade de persistencia

<?xml version="1.0" encoding="UTF-8"?>  
  
<persistence>  
    <persistence-unit name="puMosaicoDigital">  
        <properties>  
            <property name="hibernate.archive.autodetection" value="class, hbm" />  
              
            <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" />  
            <property name="hibernate.connection.driver_class" value="org.postgresql.Driver" />  
            <property name="hibernate.connection.url" value="jdbc:postgresql://localhost:5435/Mosaico" />  
            <property name="hibernate.connection.username" value="postgres" />  
            <property name="hibernate.connection.password" value="eguru" />  
            <property name="hibernate.show_sql" value="true" />  
            <property name="hibernate.format_sql" value="true" />  
            <property name="hibernate.hbm2ddl.auto" value="update" />  
        </properties> 
        <session-factory> 
          ...
          <mapping class="Pessoa" />
          <mapping class="Professor" />
          ...
        </session-factory>
    </persistence-unit>  
</persistence>  

Trabalha eu e meu amigo aqui. Nós mudamos as classes Pessoa e Professor e ficou assim. Precisa realmente com JPA desse mapeamento?

@Entity @Table(name="professor") @PrimaryKeyJoinColumn(name="idpessoa") public class Professor extends Pessoa { @Column(name="foto") private String foto; public String getFoto() { return foto; } public void setFoto(String foto) { this.foto = foto; } }

@Entity @Table(name="pessoa") @Inheritance(strategy=InheritanceType.JOINED) @SequenceGenerator(name="seq_pessoa", sequenceName="pessoa_idpessoa_seq", allocationSize=1) public class Pessoa { @Id @Column(name="idPessoa") @GeneratedValue(strategy=GenerationType.SEQUENCE, generator="seq_pessoa") private int idPessoa; @Column(name="nome") private String nome; @Column(name="sobrenome") private String sobrenome; @Enumerated(EnumType.STRING) private EnumSexo sexo; @Column(name="cpf") private String cpf; @Column(name="telefoneComercial") private String telefoneComercial; @Column(name="telefoneResidencial") private String telefoneResidencial; @Column(name="email") private String email; @Enumerated(EnumType.STRING) private EnumTipoPessoa tipo; @OneToOne(mappedBy="pessoa") private Login login; public int getIdPessoa() { return idPessoa; } public void setIdPessoa(int idPessoa) { this.idPessoa = idPessoa; } public String getNome() { return nome; } public void setNome(String nome) { this.nome = nome; } public String getSobrenome() { return sobrenome; } public void setSobrenome(String sobrenome) { this.sobrenome = sobrenome; } public EnumSexo getSexo() { return sexo; } public void setSexo(EnumSexo sexo) { this.sexo = sexo; } public String getCpf() { return cpf; } public void setCpf(String cpf) { this.cpf = cpf; } public String getTelefoneComercial() { return telefoneComercial; } public void setTelefoneComercial(String telefoneComercial) { this.telefoneComercial = telefoneComercial; } public String getTelefoneResidencial() { return telefoneResidencial; } public void setTelefoneResidencial(String telefoneResidencial) { this.telefoneResidencial = telefoneResidencial; } public String getEmail() { return email; } public void setEmail(String email) { this.email = email; } public EnumTipoPessoa getTipoPessoa() { return tipo; } public void setTipoPessoa(EnumTipoPessoa tipo) { this.tipo = tipo; } public Login getLogin() { return login; } public void setLogin(Login login) { this.login = login; } }

Precisa sim, se não tiver o mapeamento o JPA não consegue identificar suas classes

Esse mapeamento eu faço no persistence? Só uma pergunta. Após eu ter mudado as classes, agora ele me diz que não encontra o campo idpessoa na entidade Professor. Ele não enxerga isso:

@Entity @Table(name="professor") @PrimaryKeyJoinColumn(name="idpessoa") public class Professor extends Pessoa {
Como eu faço esse mapeamento?

Para que o hibernate saiba quais são as classes que serão utilizadas, você precisa adicionar ao hibernate.cfg.xml.

[quote=joede.fadel]faltou você mapear as suas classes no na sua unidade de persistencia

[code]

<?xml version="1.0" encoding="UTF-8"?>
        <property name="hibernate.dialect" value="org.hibernate.dialect.PostgreSQLDialect" />    
        <property name="hibernate.connection.driver_class" value="org.postgresql.Driver" />    
        <property name="hibernate.connection.url" value="jdbc:postgresql://localhost:5435/Mosaico" />    
        <property name="hibernate.connection.username" value="postgres" />    
        <property name="hibernate.connection.password" value="eguru" />    
        <property name="hibernate.show_sql" value="true" />    
        <property name="hibernate.format_sql" value="true" />    
        <property name="hibernate.hbm2ddl.auto" value="update" />    
    </properties>   
    <session-factory> 
      <!-- Aqui você adiciona as classes -->
      ...
      <mapping class="Pessoa" />
      <mapping class="Professor" />
      ...
    </session-factory>
</persistence-unit>  
[/code][/quote]

[quote=pjava]Esse mapeamento eu faço no persistence? Só uma pergunta. Após eu ter mudado as classes, agora ele me diz que não encontra o campo idpessoa na entidade Professor. Ele não enxerga isso:

@Entity @Table(name="professor") @PrimaryKeyJoinColumn(name="idpessoa") public class Professor extends Pessoa {
Como eu faço esse mapeamento?[/quote]

Esse mapeamento serve para dizer que a sua classe é uma unidade de persistência, mais não é mapeada pelo hibernate, as annotations servem para substituir os arquivos xml da classe, em versões anteriores do hibernate você tinha além de fazer o hibernate.cfg.xml, você tinha que fazer um xml para cada classe.