JPA - Criteria (JOIN)

Olá, pessoal!!

Estou tentando query para usar filtro do usuario para retornar as linhas. verdade era 2 linhas, mas retornaram 3 linhas.

Veja que criei a criteria

[code]
public List getTurmasByProfessor(Usuario u) {
EntityManager em = getEntityManager();

    List<Turma> lista = new Vector<Turma>();

    try {
        CriteriaBuilder cb = em.getCriteriaBuilder();
        CriteriaQuery cq = cb.createQuery();
        cq.select(cq.from(Turma.class));
        Root<Turma> rt = cq.from(Turma.class);
        Root<Professor> rp = cq.from(Professor.class);
        Root<Usuario> ru = cq.from(Usuario.class);
        cq.where(cb.equal(ru, u));

        Query query = em.createQuery(cq);

        lista = query.getResultList();
    } finally {
        em.close();
    }

return lista;
}[/code]

Como o querie em baixo.

select t.*
from turma t
inner join professor p
on t.professor = p.matriculaProfessor
inner join usuario u
on p.usuario = u.idUsuario
where u.idUsuario = 3;

Espero que me ajuda e dar dicas, obrigado!!!

Por acaso a 3º linha é repetida de uma das outras duas ?

[quote=fdiaz2011]Por acaso a 3º linha é repetida de uma das outras duas ?
[/quote]

Quer dizer que tá repetido o código em baixo? Deve excluir?

cq.select(cq.from(Turma.class));  
Root<Turma> rt = cq.from(Turma.class);  

Não…
Vc disse q era pra retornar 2 linhas no resultado, mas retornaram 3.
Essa q retornou a mais é igual (cópia) a alguma outra ?

[quote=fdiaz2011]Não…
Vc disse q era pra retornar 2 linhas no resultado, mas retornaram 3.
Essa q retornou a mais é igual (cópia) a alguma outra ?[/quote]

Desculpa! Eu entendo mais ou menos, mas eu usei no filtro do usuario cq.where(cb.equal(ru, u)); correto? Esse é para retornar 2 linhas,
Exemplo

Turma Professor
T20 João
T35 Antonio
T64 João

usar o filtro do usuario quando usuario foi acessado é João e deve retornar duas linhas. Criei os tabelas como Join em baixo.

CriteriaQuery cq = cb.createQuery();
cq.select(cq.from(Turma.class));
Root rt = cq.from(Turma.class);
Root rp = cq.from(Professor.class);
Root ru = cq.from(Usuario.class);
cq.where(cb.equal(ru, u));

Ou seja deve criar Join quando juntas entre as tabelas.

Olha, está meio confuso isso ai.
Não precisa disso tudo.

Como estão suas entidades Usuario, Turma e Professor ?

[quote=fdiaz2011]Olha, está meio confuso isso ai.
Não precisa disso tudo.

Como estão suas entidades Usuario, Turma e Professor ?[/quote]

Esse modelo ER que está tudo criado, mas vou mostrar 3 entidades veja em baixo.

Entidade Usuario

[code]
@Entity
@Table(name = “usuario”)
@XmlRootElement
@NamedQueries({
@NamedQuery(name = “Usuario.findAll”, query = “SELECT u FROM Usuario u”),
@NamedQuery(name = “Usuario.findByIdUsuario”, query = “SELECT u FROM Usuario u WHERE u.idUsuario = :idUsuario”),
@NamedQuery(name = “Usuario.findByUsuario”, query = “SELECT u FROM Usuario u WHERE u.usuario = :usuario”),
@NamedQuery(name = “Usuario.findBySenha”, query = “SELECT u FROM Usuario u WHERE u.senha = :senha”),
@NamedQuery(name = “Usuario.findByNome”, query = “SELECT u FROM Usuario u WHERE u.nome = :nome”),
@NamedQuery(name = “Usuario.findByEmail”, query = “SELECT u FROM Usuario u WHERE u.email = :email”),
@NamedQuery(name = “Usuario.findLogarUsuario”, query = “SELECT u FROM Usuario u WHERE u.usuario = :usuario and u.senha = :senha”),
@NamedQuery(name = “Usuario.verificaExiteUsuario”, query = “SELECT count(u) FROM Usuario u WHERE u.usuario = :usuario and u.senha = :senha”)})
public class Usuario implements Serializable {

private static final long serialVersionUID = 1L;
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Basic(optional = false)
@Column(name = "idUsuario")
private Integer idUsuario;
@Size(max = 45)
@Column(name = "usuario")
private String usuario;
@Size(max = 15)
@Column(name = "senha")
private String senha;
@Size(max = 45)
@Column(name = "nome")
private String nome;
// @Pattern(regexp="[a-z0-9!#$%&'*+/=?^_`{|}~-]+(?:\\.[a-z0-9!#$%&'*+/=?^_`{|}~-]+)*@(?:[a-z0-9](?:[a-z0-9-]*[a-z0-9])?\\.)+[a-z0-9](?:[a-z0-9-]*[a-z0-9])?", message="E-mail inválido")//if the field contains email address consider using this annotation to enforce field validation
@Size(max = 30)
@Column(name = "email")
private String email;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "usuario")
private Collection<Aluno> alunoCollection;
@JoinColumn(name = "permissao", referencedColumnName = "idPermissao")
@ManyToOne(optional = false)
private Permissao permissao;
@OneToMany(cascade = CascadeType.ALL, mappedBy = "usuario")
private Collection<Professor> professorCollection;

public Usuario() {
}

public Usuario(Integer idUsuario) {
    this.idUsuario = idUsuario;
}

public Integer getIdUsuario() {
    return idUsuario;
}

public void setIdUsuario(Integer idUsuario) {
    this.idUsuario = idUsuario;
}

public String getUsuario() {
    return usuario;
}

public void setUsuario(String usuario) {
    this.usuario = usuario;
}

public String getSenha() {
    return senha;
}

public void setSenha(String senha) {
    this.senha = senha;
}

public String getNome() {
    return nome;
}

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

public String getEmail() {
    return email;
}

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

@XmlTransient
public Collection<Aluno> getAlunoCollection() {
    return alunoCollection;
}

public void setAlunoCollection(Collection<Aluno> alunoCollection) {
    this.alunoCollection = alunoCollection;
}

public Permissao getPermissao() {
    return permissao;
}

public void setPermissao(Permissao permissao) {
    this.permissao = permissao;
}

@XmlTransient
public Collection<Professor> getProfessorCollection() {
    return professorCollection;
}

public void setProfessorCollection(Collection<Professor> professorCollection) {
    this.professorCollection = professorCollection;
}

@Override
public int hashCode() {
    int hash = 0;
    hash += (idUsuario != null ? idUsuario.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 Usuario)) {
        return false;
    }
    Usuario other = (Usuario) object;
    if ((this.idUsuario == null && other.idUsuario != null) || (this.idUsuario != null && !this.idUsuario.equals(other.idUsuario))) {
        return false;
    }
    return true;
}

@Override
public String toString() {
    return "Entidades.Usuario[ idUsuario=" + idUsuario + " ]";
}

}[/code]

Entidade Professor

@Entity
@Table(name = "professor")
@XmlRootElement
@NamedQueries({
    @NamedQuery(name = "Professor.findAll", query = "SELECT p FROM Professor p"),
    @NamedQuery(name = "Professor.findByMatriculaProfessor", query = "SELECT p FROM Professor p WHERE p.matriculaProfessor = :matriculaProfessor"),
    @NamedQuery(name = "Professor.findByRamal", query = "SELECT p FROM Professor p WHERE p.ramal = :ramal"),
    @NamedQuery(name = "Professor.findByEspecialista", query = "SELECT p FROM Professor p WHERE p.especialista = :especialista")})
public class Professor implements Serializable {

    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "matriculaProfessor")
    private Integer matriculaProfessor;
    @Column(name = "ramal")
    private Integer ramal;
    @Size(max = 20)
    @Column(name = "especialista")
    private String especialista;
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "professor")
    private Collection<Turma> turmaCollection;
    @JoinColumn(name = "usuario", referencedColumnName = "idUsuario")
    @ManyToOne(optional = false)
    private Usuario usuario;
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "autor")
    private Collection<Feed> feedCollection;

    public Professor() {
    }

    public Professor(Integer matriculaProfessor) {
        this.matriculaProfessor = matriculaProfessor;
    }

    public Integer getMatriculaProfessor() {
        return matriculaProfessor;
    }

    public void setMatriculaProfessor(Integer matriculaProfessor) {
        this.matriculaProfessor = matriculaProfessor;
    }

    public Integer getRamal() {
        return ramal;
    }

    public void setRamal(Integer ramal) {
        this.ramal = ramal;
    }

    public String getEspecialista() {
        return especialista;
    }

    public void setEspecialista(String especialista) {
        this.especialista = especialista;
    }

    @XmlTransient
    public Collection<Turma> getTurmaCollection() {
        return turmaCollection;
    }

    public void setTurmaCollection(Collection<Turma> turmaCollection) {
        this.turmaCollection = turmaCollection;
    }

    public Usuario getUsuario() {
        return usuario;
    }

    public void setUsuario(Usuario usuario) {
        this.usuario = usuario;
    }

    @XmlTransient
    public Collection<Feed> getFeedCollection() {
        return feedCollection;
    }

    public void setFeedCollection(Collection<Feed> feedCollection) {
        this.feedCollection = feedCollection;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (matriculaProfessor != null ? matriculaProfessor.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 Professor)) {
            return false;
        }
        Professor other = (Professor) object;
        if ((this.matriculaProfessor == null && other.matriculaProfessor != null) || (this.matriculaProfessor != null && !this.matriculaProfessor.equals(other.matriculaProfessor))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "Entidades.Professor[ matriculaProfessor=" + matriculaProfessor + " ]";
    }
}

Entidade Turma

@Entity
@Table(name = "turma")
@XmlRootElement
@NamedQueries({
    @NamedQuery(name = "Turma.findAll", query = "SELECT t FROM Turma t"),
    @NamedQuery(name = "Turma.findByCodTurma", query = "SELECT t FROM Turma t WHERE t.codTurma = :codTurma"),
    @NamedQuery(name = "Turma.findByHorario", query = "SELECT t FROM Turma t WHERE t.horario = :horario"),
    @NamedQuery(name = "Turma.findByEstado", query = "SELECT t FROM Turma t WHERE t.estado = :estado")})
public class Turma implements Serializable {
    private static final long serialVersionUID = 1L;
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    @Basic(optional = false)
    @Column(name = "codTurma")
    private Integer codTurma;
    @Column(name = "horario")
    @Temporal(TemporalType.TIMESTAMP)
    private Date horario;
    @Column(name = "estado")
    private Integer estado;
    @JoinColumn(name = "professor", referencedColumnName = "matriculaProfessor")
    @ManyToOne(optional = false)
    private Professor professor;
    @JoinColumn(name = "disciplina", referencedColumnName = "codDisciplina")
    @ManyToOne(optional = false)
    private Disciplina disciplina;
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "turma1")
    private Collection<Notas> notasCollection;

    public Turma() {
    }

    public Turma(Integer codTurma) {
        this.codTurma = codTurma;
    }

    public Integer getCodTurma() {
        return codTurma;
    }

    public void setCodTurma(Integer codTurma) {
        this.codTurma = codTurma;
    }

    public Date getHorario() {
        return horario;
    }

    public void setHorario(Date horario) {
        this.horario = horario;
    }

    public Integer getEstado() {
        return estado;
    }

    public void setEstado(Integer estado) {
        this.estado = estado;
    }

    public Professor getProfessor() {
        return professor;
    }

    public void setProfessor(Professor professor) {
        this.professor = professor;
    }

    public Disciplina getDisciplina() {
        return disciplina;
    }

    public void setDisciplina(Disciplina disciplina) {
        this.disciplina = disciplina;
    }

    @XmlTransient
    public Collection<Notas> getNotasCollection() {
        return notasCollection;
    }

    public void setNotasCollection(Collection<Notas> notasCollection) {
        this.notasCollection = notasCollection;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (codTurma != null ? codTurma.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 Turma)) {
            return false;
        }
        Turma other = (Turma) object;
        if ((this.codTurma == null && other.codTurma != null) || (this.codTurma != null && !this.codTurma.equals(other.codTurma))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return "Entidades.Turma[ codTurma=" + codTurma + " ]";
    }
    
}

Espero que me dá dicas ou melhorar escrever na criteria. Obrigado!

@OneToMany(cascade = CascadeType.ALL, mappedBy = "usuario")  
    private Collection<Aluno> alunoCollection;  
    @JoinColumn(name = "permissao", referencedColumnName = "idPermissao")  
    @ManyToOne(optional = false)  
    private Permissao permissao;  
    @OneToMany(cascade = CascadeType.ALL, mappedBy = "usuario")  
    private Collection<Professor> professorCollection; 

O relacionamento entre usuário e professor não me parece correto.
Pq vc ta dizendo q um usuário pode pertencer a vários professores.
A mesma coisa para alunos.
Cada aluno e cada professor não tem seu próprio e único usuário ?
Pra mim, deveria ser OnteToOne.

Vc já tendo um usuario (do tipo professor) já teria um professor automaticamente devido ao relacionamento OneToOne e esse teria as turmas já carregadas se fosse EAGER.

Se não tiver isso, usando criteria pode fazer algo tipo assim:

public List<Turma> getTurmasByProfessor(Usuario u) {  
     Criteria criteria = professorDao.getSession().createCriteria(Professor.class);
     //busca por professor atraves do id do usuario
     criteria.add( Restrictions.eq( "usuario", u.getId()) );
     Professor professor = criteria.uniqueResult();

     //dependendo do seu mapeamento a lista de turmas sera carregada automaticamente
     return professor.getTurmas();
}

[quote=fdiaz2011] @OneToMany(cascade = CascadeType.ALL, mappedBy = "usuario") private Collection<Aluno> alunoCollection; @JoinColumn(name = "permissao", referencedColumnName = "idPermissao") @ManyToOne(optional = false) private Permissao permissao; @OneToMany(cascade = CascadeType.ALL, mappedBy = "usuario") private Collection<Professor> professorCollection;

O relacionamento entre usuário e professor não me parece correto.
Pq vc ta dizendo q um usuário pode pertencer a vários professores.
A mesma coisa para alunos.
Cada aluno e cada professor não tem seu próprio e único usuário ?
Pra mim, deveria ser OnteToOne.

Vc já tendo um usuario (do tipo professor) já teria um professor automaticamente devido ao relacionamento OneToOne e esse teria as turmas já carregadas se fosse EAGER.

Se não tiver isso, usando criteria pode fazer algo tipo assim:

[code]
public List getTurmasByProfessor(Usuario u) {
Criteria criteria = professorDao.getSession().createCriteria(Professor.class);
//busca por professor atraves do id do usuario
criteria.add( Restrictions.eq( “usuario”, u.getId()) );
Professor professor = criteria.uniqueResult();

 //dependendo do seu mapeamento a lista de turmas sera carregada automaticamente
 return professor.getTurmas();

}
[/code][/quote]

Esse modelo ER são one a one entre tabela usuario e professor, mas a ferramenta netbeans gerou entidades automatica e criou oneToMany aquele entidade. Olhei e achei estranho, mas não mexi anotação da entidades. Já tinha pensando era OneToOne.

Como fazer anotação da entidade OneToOne entre usuario para professor, usuario para aluno.

Em professor e em aluno vc coloca:

@OneToOne
private Usuario usuario;

Se vc quiser ter acesso ao professor e ao aluno pelo usuário faz isso na entidade Usuario:

@OneToOne(mappedBy = "usuario")
private Professor professor;

@OneToOne(mappedBy = "usuario")
private Aluno aluno;