[ resolvido] Utilizar criteria sem session, é possível?

Olá pessoal…
Sinceramente… estou… perdida… :frowning:
Me desculpem se eu falar algo de errado… mas, após horas de pesquisas, eu cheguei à seguinte conclusão…

Meu sistema é desktop, utilizo hibernate jpa hibernate validator…
Tenho classes Entity com relacionamento @manytomany.

1. Conforme pesquisei, para fazer uma consulta utlizando essas classes mxn preciso utilizar criteria, correto?
2. Pra isso, preciso ter uma Session()… correto??
3. No meu sistema que é Desktop, tenho a classe Conexao com o seguinte:

package dao;

import javax.persistence.EntityManager;
import javax.persistence.EntityManagerFactory;
import javax.persistence.Persistence;
import model.Usuario;

/**
 *
 * @author Dina 
 */
public class Conexao {

    private static EntityManagerFactory fabricaDAO = Persistence.createEntityManagerFactory("SPoliClinicPU");
    private static Usuario usuarioLogado;

    public static EntityManager getEM() {
         EntityManager dao = fabricaDAO.createEntityManager();
         return(dao);
    }

    public static Usuario getUsuario() {
        return usuarioLogado;
    }

    public static void setUsuario(Usuario usuario) {
        Conexao.usuarioLogado = usuario;
    }

}

4. Pessoal, no meu caso, como eu poderia utilizar criteria? Há algum jeito?Obrigada…!!

1 - Certo!
2 - Certo
4 - Nao! Pelo que eu conheco nao se pode fazer criterias sem Session aberta
Criterias sao feitos pra vc nao utilizar os HQLs ou os proprios SQLs (nao que nao tenha que saber)
pra utilizar o Criteria, eu geralmente no Hibernate faço assim:

// ai vai algumas criterias:
 List <Aluno>lista_query = 
                                        HibernateUtil //no meu caso Utilizo essa classe para manipuilar as conexoes
                                        .getSession() // suaFabrica.getSession();
                                        .createCriteria(Aluno.class)  //voce seta a classe que quer usar para pesquisar

                                        .setFirstResult(0)//pega o primeiro resultado que eu quero pegar
                                        .setMaxResults(10)//pega a quantidade de resultados desejada
                                        .addOrder( Order.desc("aluno_nome") )//adiciona a ordenacao, se eh tipo asc ou desc
                                        .add(  Restrictions.between("aluno_codigo", 1, 5) )//filtra entre codigos, passondo o objeto                            
                                         .add( Expression.eq("aluno_nome", "quero filtrar") )//filtra os dados do bancos de dados, 

                                        .list();//converte para Lista

lembrando que os parametros string que eu passo é o que esta no meu Objeto
tenho um metodo pra verificar se determinado elemento existe e tal:

/**
     *  Metodo Boolean que retorna se encontra ou nao um determinado registro
     * Seus parametros sao 
     * Class classe: Parametro necessario, pois pega a classe a ser pesquisada
     * String strToFilter: palavra que se deseja buscar dentro do Banco de Dados
     * String fieldHQLFilter: campo que se deseja buscar a palavra
     */
    public static boolean findRecord( Class classe , String strToFilter , String fieldHQLFilter)
    {
        HibernateUtil.getSession().clear();
        return   HibernateUtil
                    .getSession()
                   .createCriteria( classe )
                   .add( Restrictions.eq( fieldHQLFilter , strToFilter))
                   .equals(StrToFilter); //Retorna true se a string foi encontrada
}

espero ter ajudado

jperondi, obrigada pela resposta!!!
E pelo exemplo!!!

Certo, então para utilizar Criteria preciso de Session.
Levando em conta que o meu sistema é Desktop e que eu já tenho a classe Conexao.java para a minha conexão com o BD (conforme mostrei no meu 1º post), teria alguma lógica eu criar Session com a finalidade de utilizar criteria??

Outra pergunta: Caso eu não utilize criteria, a minha consulta MxN ficaria nos namedQueries?

O que na verdade eu quero é que o usuário ao escolher uma especialidade, apareçam os médicos desta tal especialidade.
O relacionamento MxN entre as classes Entitys Medico e Especialidade gerou a tabela medico_especialidade.

To quebrando a cabeça, já fiz mil e uma mudanças, a última ficou assim na classe Entity Medico:

@NamedQueries({
    @NamedQuery(name="buscarMedicosEspecialidade", query="select medico from Medico medico where medico.id = :codigopessoa and medico.id in (select especialidademedico from Especialidade_Medico especialidademedico where especialidademedico.especialidade.id = :codigoespecialidade and especialidademedico.medico.id = :codigopessoa2)")
})

E na classe DaoMeidco

    public Iterator consultarMedicoEspecialidade(Medico med, Especialidade esp){
        EntityManager dao = Conexao.getEM();

        Query query = dao.createNamedQuery("buscarMedicosEspecialidade");
        query.setParameter("codigopessoa", med.getCodigoPessoa());
        query.setParameter("codigoespecialidade", esp.getCodigoEspecialidade());
        query.setParameter("codigopessoa2", med.getCodigoPessoa());

        List<Medico> resultados = query.getResultList();
        Iterator<Medico> iteradorEspPlano = resultados.iterator();

        dao.close();
        return iteradorEspPlano;

    }

E nadaaaa funciona… :frowning: Não sei o correto a fazer… se puder me ajudar, agradeço muito!

Desculpa, mas nao entendo muito de JPA
Trabalho com annotations nao com EM
Acho que seria uma boa fazer um teste, se o Criteria resolver seu problema

Se sua classe Medico tem uma Collections de Especialidades, dar um get no Pojo e ele retorna a colecao de especialidades
a mesma coisa pra especialidades.

posta sua Classe Medico e sua Classe especialidades pra ficar de melhor entendimento do modo que vc esta fazendo

jperondi, obrigada novamente pela ajuda!

Não tinha pensado no que vc falou!!! Acho que já estou meio… surtada… :shock:
hehe

Bom, mas pra isso, eu teria que fazer uma query com um select na minha tabela medico_especialidade, teria que buscar o código no caso, da especialidade, e ver quais códigos de médicos tem essa especialidade, certo??
Feito isso, faria uma outra query para resgatar os nomes dos médicos com os ids que eu passei a ter com a query acima??
É isso??

Tem alguma forma mais “simples”?

Obrigada novamente!!
As minhas classes são:

package model;

import java.util.List;
import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.JoinColumn;
import javax.persistence.JoinTable;
import javax.persistence.ManyToMany;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.persistence.PrimaryKeyJoinColumn;
import javax.validation.constraints.Size;

/**
 *
 * @author Dina
 */
@Entity
@NamedQueries({
    @NamedQuery(name="buscarTodosMedicos", query="select medico from Medico medico order by medico.nome")
})
@PrimaryKeyJoinColumn(name="codigoPessoa", referencedColumnName="codigoPessoa")
public class Medico extends Funcionario {

    @Column(nullable=false, length=20, unique=true)
    private String crm;

    @ManyToMany(targetEntity=Especialidade.class)
    @JoinTable(name="medico_especialidade", joinColumns=@JoinColumn(name="codigopessoa"), inverseJoinColumns=@JoinColumn(name="codigoespecialidade"))
   // @NotEmpty(message="Você deve selecionar pelo menos 1 especialidade")
    private List<Especialidade> especialidades = null;

    @Size(min=1, message="O campo *CRM* deve ser preenchido")
    public String getCrm() {
        return crm;
    }

    public List<Especialidade> getEspecialidades() {
        return especialidades;
    }


    public void setCrm(String crm) {
        this.crm = crm;
    }

    public void setEspecialidades(List<Especialidade> especialidades) {
        this.especialidades = especialidades;
    }
}
package model;

import java.io.Serializable;

import javax.persistence.Column;
import javax.persistence.Entity;
import javax.persistence.GeneratedValue;
import javax.persistence.GenerationType;
import javax.persistence.Id;
import javax.persistence.NamedQueries;
import javax.persistence.NamedQuery;
import javax.validation.constraints.Min;
import javax.validation.constraints.Size;

/**
 *
 * @author Dina
 */
@Entity
@NamedQueries({
    @NamedQuery(name="buscarTodosEspecialidade", query="select especialidade from Especialidade especialidade order by especialidade.nome")
})
public class Especialidade implements Serializable{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Long codigoEspecialidade;
    @Column(length=30, nullable=false)
    private String nome;
    @Column(nullable=false)
    private boolean ativo;
    @Column(nullable=false)
    private double precoParticular;

    public Long getCodigoEspecialidade() {
        return codigoEspecialidade;
    }

    public boolean isAtivo() {
        return ativo;
    }
    
    @Size(min=1, message="O campo *Nome* deve ser preenchido")
    public String getNome() {
        return nome;
    }


    @Min(value=1, message="Digite um preço válido no campo *Preço Particular*")
    public double getPrecoParticular() {
        return precoParticular;
    }


    public void setCodigoEspecialidade(Long codigoEspecialidade) {
        this.codigoEspecialidade = codigoEspecialidade;
    }

    public void setAtivo(boolean ativo) {
        this.ativo = ativo;
    }

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

    public void setPrecoParticular(double precoParticular) {
        this.precoParticular = precoParticular;
    }

    @Override
    public int hashCode() {
        int hash = 0;
        hash += (codigoEspecialidade != null ? codigoEspecialidade.hashCode() : 0);
        return hash;
    }

    @Override
    public boolean equals(Object object) {
        // TODO: Warning - this method won't work in the case the codigoEspecialidade fields are not set
        if (!(object instanceof Especialidade)) {
            return false;
        }
        Especialidade other = (Especialidade) object;
        if ((this.codigoEspecialidade == null && other.codigoEspecialidade != null) || (this.codigoEspecialidade != null && !this.codigoEspecialidade.equals(other.codigoEspecialidade))) {
            return false;
        }
        return true;
    }

    @Override
    public String toString() {
        return getNome();
    }

}

na sua classe especialidades coloca

// especialidadesCollection seria uma lista interna de especialidades public List<Medico> getMedicoCollection() { return medicoCollection; }

Classe Médico

// especialidadesCollection seria uma lista interna de medico
    public List<Especialidade> getEspecialidadeCollection() {
        return especialidadeCollection;
    }

ai quando vc selecionar o medico, faz assim:

      Medico med = (Medico)suaSessao.getSession().get(Medico.class, 1); //1 é a sua, a PK do médico que vc deseja concsultar
      List <Especialidades>listaEspecialidades = etap.getEspecialidadesaCollection();
     // ai sua lista vc adiciona na outra tabela, entende?
     // a mesma coisa pra tabela especialidades e medico

assim que eu faço por aqui,
pq nos annotations tbm uso JPA pra implementar
testa ai

jperondi,

Mas, no caso eu teria que trabalhar com sessão correto?

Aí é que está o ponto. A única forma de fazer esse tipo de consulta é com sessão??

Não sei se eu estou errada, mas sessão faz mais sentido em sw web, ou estou errada?

Obrigada novamente!

Sim
Sim
O uso da Sessao te tira os SQLs da vida, pois so dar um get, transformar pra lista e etc.
ou entao utilizar HQLs inves de SQL, pode ser feita tanto pra desk quanto pra web
lembrando que a session que eu to falando é do Hibernate…
pq ele inibe vc de ficar se preocupando com o SQL, com consultas Cabulosas,
se seu projeto é novo, sugiro a migrar pra Annotations e Hibernate, pq ai vc vai se preocupar so com a logica
e se vc fizer o mapeamento dos objetos, pode criar diretamente do Java, nao precisando fazer aquele bom e velho
Select * from medicos where especializacoes e bla bla bla

jperondi, muito obrigada pelos esclarecimentos!!!
Obrigada mesmo!!
Acho que vou utilizar Session então!
Realmente facilita muito!!
Obrigada mesmo!!!
:slight_smile:

de nada as ordens
se precisar so dar um grito por mp