JPA - Criteria (JOIN)

9 respostas
J

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
public List<Turma> 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;
    }
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!!!

9 Respostas

F

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

J

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

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);
F

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 ?

J

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 ?

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.

F

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

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

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

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

Esse modelo ER que está tudo criado, mas vou mostrar 3 entidades veja em baixo.
[img]http://2.bp.blogspot.com/-KoacdYiIMYI/UbvH-QREdCI/AAAAAAAAC-Y/4M7sRRlHwFc/s1600/MODELO+ER+da+agenda+Faculdade+LPI2.PNG[/img]

Entidade Usuario
@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 + " ]";
    }
}
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!

F
@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();
}
J
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:
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();
}

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.

F

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;
Criado 18 de junho de 2013
Ultima resposta 18 de jun. de 2013
Respostas 9
Participantes 2