~* em JPA

46 respostas
jaissonduarte

oi pessoal estou trabalhando com consultas em JPA
numa consulta normal @NamedQuery(name = "Area.findByDescricao", query = "SELECT a FROM Area a WHERE a.descricao = :descricao")
funciona

em SQL essa consulta funciona numa boa

select * from area where descricao ~* 'o'

mas quando eu coloco

não funciona e da esse erro:


Erro durante a implantação: Exception while preparing the app : Exception [EclipseLink-8025] (Eclipse Persistence Services - 2.3.2.v20111125-r10461): org.eclipse.persistence.exceptions.JPQLException
Exception Description: Syntax error parsing the query [Area.findByDescricao: select * from area where descricao ~* descricao], line 1, column 8: unexpected token [*].
Internal Exception: NoViableAltException(93@[330:16: ( DISTINCT )?]). Consulte o server.log para obter informações detalhadas.
/home/jaisson/Área de Trabalho/pesquisaDocumento/nbproject/build-impl.xml:726: O módulo não foi implementado.
Verifique o registro do servidor para mais detalhes.
FALHA NA CONSTRUÇÃO (tempo total: 1 segundo)

pois é no banco a consulta funciona, por que no JPA não, tem como eu fazer pro JAP entender que isso funciona, ou tem outro modo de fazer

valeu

46 Respostas

Hebert_Coelho

Pra que serve o ~* ?

Rodrigo_Sasaki

é… JPQL não é exatamente igual SQL

se o ~* (que eu não faço idéia do que é hehe) não faz parte da sintaxe do JPQL, talvez por ser específico de algum banco, creio que não vá funcionar

rafaduka

Algumas abreviações, são particular para cada banco.
Para JPA neste caso poderia-se utilizar LIKE

[google]LIKE JPA[/google]

jaissonduarte

ai que coisa, a gente fala pela metade :smiley: :smiley:

bom o ~* eu uso no Postgres (não testei em outros banco)
com esse operador ele busca tudo que for parecido com o dado informado

exemplo, tenho os dados:

Informática,
Informatica,
informática,
informatica,
oi

note que tem diferenças nas palavras essas 4 palavras para nós é uma só mas para o banco são 4, como todos sabem casesentive (acho que é assim que escreve)

ai se informar o carácter “e”, ele (banco) não vai trazer nada, mas se colocar “a”, ele vai trazer tudo, menos o oi,
legal né

Hebert_Coelho

Então você terá que utilizar NativeQuery. Com isso você consegue utilizar a Query específica para o banco de dados em questão.

jaissonduarte

finalmente uma luz no fim do túnel :smiley:
como eu faço com NativeQuery tem algum exemplo?

Hebert_Coelho

jaissonduarte:
finalmente uma luz no fim do túnel :smiley:
como eu faço com NativeQuery tem algum exemplo?
Tenho não. Google c acha. [=

rafaduka

aqui

jaissonduarte
e ai pessoal seguindo esse site: http://www.codemiles.com/jpa/named-native-query-t6203.html fiz isso:
@Entity
@Table(name = "area")
@XmlRootElement
@NamedNativeQuery(name="findByDescricao",query="SELECT * a FROM Area a WHERE a.descricao ~* descricao", resultClass=Area.class)
/*@NamedQueries({
    @NamedQuery(name = "Area.findAll", query = "SELECT a FROM Area a"),
    @NamedQuery(name = "Area.findByCodigo", query = "SELECT a FROM Area a WHERE a.codigo = :codigo"),
    /*@NamedQuery(name = "Area.findByDescricao", query = "select * from area where descricao ~* descricao")})*/
public class Area implements Serializable {
    private static final long serialVersionUID = 1L;
    //public static final String pesquisar
   public static final String pesquisarDescricao="findByDescricao";
    @Id
    @Basic(optional = false)
    @NotNull
    @Column(name = "codigo")
    private Integer codigo;
    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 30)
    @Column(name = "descricao")
    private String descricao;
e :
Stateless
public class AreaDAO {

    @PersistenceContext(name = "pesquisaDocumentoPU")
    private EntityManager em;
    private Area area;

    public List<Area> pesquisar(String descricao) {
        List<Area> areas = null;
        try {
            Query query = em.createNativeQuery(Area.pesquisarDescricao);
            query.setParameter("descricao", descricao);
            areas = query.getResultList();
            return areas;
        } catch (Exception e) {
            System.out.println("erro "+e.getMessage());
        }
        return areas;
    }

e da esse erro:


Informações: erro
Internal Exception: org.postgresql.util.PSQLException: ERROR: syntax error at or near "findByDescricao"
Error Code: 0
Call: findByDescricao
Query: DataReadQuery(sql="findByDescricao")

o que vocês acham que pode ser?

Hebert_Coelho

Novamente, você tem que usar NativeQuery e não NamedQuery. NamedQuery utiliza JPQL e não tem suporte ao ~*. NativeQuery você consegue utilizar sintax do banco mesmo.

jaissonduarte
jakefrog:
Novamente, você tem que usar NativeQuery e não NamedQuery. NamedQuery utiliza JPQL e não tem suporte ao ~*. NativeQuery você consegue utilizar sintax do banco mesmo.
????? mas estou usando o NativeQuery, até comentei minhas NamedQuery no site o cara fez isso:
@NamedNativeQuery(name = "nativeTopicByDate", query = "SELECT topic.TITLE, topic.CREATION_DATE FROM TOPIC topic " +
        "WHERE topic.MODIFED_DATE=?", resultClass = Topic.class)
e eu:
@Entity
@Table(name = "area")
@NamedNativeQuery(name="findByDescricao",query="SELECT * a FROM Area a WHERE a.descricao ~* descricao", resultClass=Area.class)
public class Area implements Serializable {   
    public static final String pesquisarDescricao="findByDescricao";
    .....
ele:
public  List<Topic> loadTopicByDate(Date date) {
    Query query = entityManager.createNativeQuery("nativeTopicByDate");
    query.setParameter(1, date);
 
    List<Topic> topicList = query.getResultList();
    return topicList;
    }
eu:
public List<Area> pesquisar(String descricao) {
        List<Area> areas = null;
        try {
            Query query = em.createNativeQuery(Area.pesquisarDescricao);
            query.setParameter("descricao", descricao);
            areas = query.getResultList();
            return areas;
        } catch (Exception e) {
            System.out.println("erro "+e.getMessage());
        }
        return areas;
    }
e o erro: Informações: erro Internal Exception: org.postgresql.util.PSQLException: ERROR: syntax error at or near "findByDescricao" Error Code: 0 Call: findByDescricao Query: DataReadQuery(sql="findByDescricao")

que coisa não? :D

Hebert_Coelho

Ops! Não vi direito. Mals! :oops:

Olha isso: SELECT * a FROM Area a WHERE a.descricao ~* descricao

troque * a por * apenas. :lol:

Outra coisa, troque de descricao para :descricao . :lol:

jaissonduarte

jakefrog:

troque * a por * apenas. :lol:
Outra coisa, troque de descricao para :descricao . :lol:

será que você quis dizer assim?

deu esse erro:
Internal Exception: org.postgresql.util.PSQLException: ERROR: syntax error at or near "findByDescricao"
Error Code: 0
Call: findByDescricao
Query: DataReadQuery(sql=“findByDescricao”)

Hebert_Coelho

Se você rodar SELECT * FROM Area WHERE descricao ~* :descricao direto no postgres ele funciona? Trocando o :descricao por algum valor válido?

jaissonduarte

roda que é uma beleza,

daqui a pouco vou deixar meu sistema com usabilidade -5

Hebert_Coelho

Tenta assim: em.createNativeQuery(“select * from area where descricao ~* :descricao”, Area.class);

Teoricamente tá tudo certo mano. O.o

jaissonduarte
Cara da uma olhada no meu código e me diga o que tem de errado
package dao;

import java.util.List;
import javax.ejb.Stateless;
import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import javax.persistence.Query;
import modelo.Area;

@Stateless
public class AreaDAO {

    @PersistenceContext(name = "pesquisaDocumentoPU")
    private EntityManager em;
    private Area area;

    public List<Area> pesquisar(String descricao) {
        List<Area> resultado = null;
        try {
            Query consulta = em.createNativeQuery("select * from area where descricao ~* :descricao", Area.class); 
            consulta.setParameter("descricao", descricao);
            resultado = consulta.getResultList();
        } catch (Exception e) {
            System.out.println("não deu hehehes: " + e.getMessage());
        }
        return resultado;
    }
}

por que esta dando esse erro:

Informações: não deu hehehes:
Internal Exception: org.postgresql.util.PSQLException: ERROR: syntax error at or near ":"
Error Code: 0
Call: select * from area where descricao ~* :descricao
Query: ReadAllQuery(referenceClass=Area sql="select * from area where descricao ~* :descricao")

quando retiro o ":"

Informações: não deu hehehes:
Exception Description: The primary key read from the row [ArrayRecord(
=> 3
=> Informática)] during the execution of the query was detected to be null. Primary keys must not contain null.
Query: ReadAllQuery(referenceClass=Area sql="select * from area where descricao ~* descricao")

tem outra forma de fazer esse consulta?

Hebert_Coelho

Faz um teste: select * from area where descricao = :descricao

e passa uma descrição que exista no banco.

Caso funcione, pode ser o driver do postgres que não está reconhecendo o comando.

jaissonduarte

quando coloco o NativeQuery da esse erro:

Internal Exception: org.postgresql.util.PSQLException: ERROR: syntax error at or near "Descricao"
Error Code: 0
Call: Descricao
Query: DataReadQuery(sql=“Descricao”)

com o NamedQuery ele funciona normal
:smiley:

Hebert_Coelho

Pq seu Descricao está com D maiúsculo?

Vc colocou como eu passei?

jaissonduarte

o descricao com D maisculo é o nome da consulta da uma olhada:

@NamedNativeQuery(name="Descricao",query="SELECT * FROM Area WHERE descricao ~* descricao") @NamedQueries({ @NamedQuery(name = "Area.findAll", query = "SELECT a FROM Area a"), @NamedQuery(name = "Area.findByCodigo", query = "SELECT a FROM Area a WHERE a.codigo = :codigo"), @NamedQuery(name = "byDescricao", query = "SELECT a FROM Area a WHERE a.descricao = :descricao")}) public class Area implements Serializable { private static final long serialVersionUID = 1L; public static final String pesquisarDescricao="byDescricao"; public static final String pesquisar="Descricao";

e:

Query consulta = em.createNativeQuery(Area.pesquisar)
Hebert_Coelho

Não cara, lah ainda continua com o ~* @NamedNativeQuery(name="Descricao",query="SELECT * FROM Area WHERE descricao ~* descricao")Faça assim: em.createNativeQuery(“select * from area where descricao = :descricao”, Area.class);

ricardobocchi

Cara, tenta executar essa query fora de uma NamedQuery, só pra testar… tipo

Query query = session.createSQLQuery("SELECT * FROM Area WHERE descricao ~* :descricao"); query.setParameter("descricao", "o"); List result = query.list();

Se não der certo, talves o driver não suporte… mas acho dificil que seja isso… De qualquer maneira, esse comando não é equivalente a isso?

Query query = session.createSQLQuery("SELECT * FROM Area WHERE UPPER(descricao) like :descricao"); query.setParameter("descricao", "%o%".toUpperCase()); List result = query.list();

Se te servir, nem precisa ser query nativa… pode ser HQL mesmo

jaissonduarte

e ai meu
cara da onde tu tirou esse session? :smiley:

ricardobocchi

tu deve ter uma sessão em algum lugar, ou um entity manager, onde tu pode executar uma sql, hql ou criteria, não?

jaissonduarte
tenho não,

o que eu tenho é um EntityManager da javax.persistence.EntityManager;

e ele não tem o createSQLQuery;

ele vem de que classe?, ou é próprio do hibernete longe do JPA
ricardobocchi

No EntityManager o nome método é createNativeQuery

http://docs.oracle.com/javaee/6/api/javax/persistence/EntityManager.html

jaissonduarte

ricardobocchi:
No EntityManager o nome método é createNativeQuery

http://docs.oracle.com/javaee/6/api/javax/persistence/EntityManager.html

pois é eu estou tentando me virar no NativeQuery :smiley:

ricardobocchi

rolou a sql?

Hebert_Coelho

Vc testou isso aqui?

jaissonduarte

testei sim :smiley:
e deu esse erro:
Exception Description: The primary key read from the row [ArrayRecord(
=> 3
=> Informática)] during the execution of the query was detected to be null. Primary keys must not contain null.
Query: ReadAllQuery(referenceClass=Area sql=“select * from area where descricao = descricao”)

vai entender nem tenho esse dado?

mas cara estava fazendo uma gambiarras medonhas e acho que meu problema é que não estou conseguindo passar os parâmetros
enfim que bom que tu voltou :smiley:

Hebert_Coelho

Coloca seu código como está do modo q eu falei para testar.

Tem que funcionar pois é um query normal.

jaissonduarte
classe modelo:
@Entity
@Table(name = "area")
@XmlRootElement
@NamedNativeQuery(name="Descricao",query="SELECT * FROM Area  WHERE descricao ~* descricao")
@NamedQueries({
    @NamedQuery(name = "Area.findAll", query = "SELECT a FROM Area a"),
    @NamedQuery(name = "Area.findByCodigo", query = "SELECT a FROM Area a WHERE a.codigo = :codigo"),
    @NamedQuery(name = "Area.Descricaos", query = "SELECT a FROM Area a WHERE a.descricao = :descricao")})
public class Area implements Serializable {
    private static final long serialVersionUID = 1L;
    public static final String pesquisarNamed = "Area.Descricaos";
    public static final String pesquisarNativa = "Descricao";
    @Id
    @Basic(optional = false)
    @NotNull
    @Column(name = "codigo")
    private Integer codigo;
    @Basic(optional = false)
    @NotNull
    @Size(min = 1, max = 30)
    @Column(name = "descricao")
    private String descricao;
casse DAO:
@Stateless
public class AreaDAO {

    @PersistenceContext(name = "pesquisaDocumentoPU")
    private EntityManager em;
    private Area area;

    public List<Area> pesquisar(String descricao) {
        List<Area> resultado = null;
        try {
            Query consulta = em.createNativeQuery("select * from area where descricao = descricao", Area.class);
            consulta.setParameter("descricao", descricao);
            resultado = consulta.getResultList();
            return resultado;
        } catch (Exception e) {
            System.out.println("não deu hehehes: " + e.getMessage());
        }
        return resultado;
    }
}
Hebert_Coelho

Mano, novamente você não colocou os : Query consulta = em.createNativeQuery(“select * from area where descricao = descricao”, Area.class);

select * from area where descricao = :descricao
Isso aqui tem que funcionar.

jaissonduarte

só que não funciona :oops:

da esse erro:
Informações: não deu hehehes:
Internal Exception: org.postgresql.util.PSQLException: ERROR: syntax error at or near ":"
Error Code: 0
Call: select * from area where descricao = :descricao
Query: ReadAllQuery(referenceClass=Area sql=“select * from area where descricao = :descricao”)

ricardobocchi

tenta

Query consulta = em.createNativeQuery("select * from area where descricao = ?", Area.class); consulta.setParameter(1, descricao);

jaissonduarte
código:
public List<Area> pesquisar(String descricao) {
        List<Area> resultado = null;
        try {
            //Query consulta = em.createNativeQuery("select * from area where descricao = descricao", Area.class);
            // consulta.setParameter("descricao", descricao);
            Query consulta = em.createNativeQuery("select * from area where descricao = ?", Area.class);
            consulta.setParameter(1, descricao);
            try {
                resultado = consulta.getResultList();
            } catch (Exception e) {
                System.out.println("erro 1" + e.getMessage());
            }

            return resultado;
        } catch (Exception e) {
            System.out.println("não deu hehehe: " + e.getMessage());
        }
        return resultado;
    }

erro:

Informações: erro 1
Exception Description: The primary key read from the row [ArrayRecord(
=> 2
=> jaisson)] during the execution of the query was detected to be null. Primary keys must not contain null.
Query: ReadAllQuery(referenceClass=Area sql="select * from area where descricao = ?")

Obs.: 2, jaisson, são dados do bd

tenhamos fé

Hebert_Coelho

Cara, deu um erro muito bizarro agora: during the execution of the query was detected to be null. Primary keys must not contain null.

Verifique seu DB se tem algum ID com campo primário null.

Hebert_Coelho

Caso todos os ids estejam preenchido, tenta trocar de Integer para int o seu id.
OBS.: Essa alteração pode quebrar seu código em um monte de lugar.

jaissonduarte
cara não sei se isso ajuda mas quando eu aprendi persistência com JDBC, meu professor criou esses métodos:
public List<Professor> getProfessores(String ordem, Integer codigo, String nome) throws ClassNotFoundException, SQLException {
        List<Professor> professores = new ArrayList<Professor>();

        String sql = "SELECT * FROM professor WHERE 1=1 " + obtemFiltros(codigo, nome) + " ORDER BY "+ordem;

        PreparedStatement ps = Conexao.getConexao().prepareStatement(sql);
        ResultSet rs = ps.executeQuery();
        while (rs.next()) {

            Professor professor = new Professor();
            professor.setCodigo(rs.getInt("codigo"));
            professor.setNome(rs.getString("nome"));
            professor.setSexo(Conversor.stringToChar(rs.getString("sexo")));
            professor.setDataAdmissao(ConverteData.enToBr(rs.getString("dt_admissao")));
            professor.setDataDemissao(ConverteData.enToBr(rs.getString("dt_demissao")));

            professores.add(professor);
        }
        return professores;
    }

     private String obtemFiltros(Integer codigo, String nome) {
        StringBuilder filtro = new StringBuilder();

        if (codigo != null) {
            filtro.append(" AND codigo = " + codigo);
        }

        if (nome != null) {
            //.replaceAll("'", "") para todas as Strings senão
            //submeto ' or 1=1  or ''='
            filtro.append(" AND nome ~* '" + nome.replaceAll("'", "")+"'");
        }

        return filtro.toString();
    }
gomesrod

Olá,

Só metendo o nariz onde não fui chamado :slight_smile:

Por que recorrer a Native Query para uma consulta simples de listagem?
Fazendo dessa forma você não vai tirar proveito da facilidade do JPA, que é justamente encapsular a conversa com o banco e tirar do desenvolvedor a preocupação com SQL.
NativeQuery foi feito para casos específicos, por exemplo quando precisar otimizar a performance de uma consulta complexa.

Se no momento não estiver com tempo suficiente para aprender a utiliza-lo, é melhor utilizar JDBC puro mesmo… do jeito que está vc tem a complexidade do JPA (reparou quantos erros está dando? esse bicho é meio sensível rsrs) sem ter as vantagens que ele proporciona!

jaissonduarte

gomesrod:
Olá,

Só metendo o nariz onde não fui chamado :slight_smile:

Por que recorrer a Native Query para uma consulta simples de listagem?
Fazendo dessa forma você não vai tirar proveito da facilidade do JPA, que é justamente encapsular a conversa com o banco e tirar do desenvolvedor a preocupação com SQL.
NativeQuery foi feito para casos específicos, por exemplo quando precisar otimizar a performance de uma consulta complexa.

Se no momento não estiver com tempo suficiente para aprender a utiliza-lo, é melhor utilizar JDBC puro mesmo… do jeito que está vc tem a complexidade do JPA (reparou quantos erros está dando? esse bicho é meio sensível rsrs) sem ter as vantagens que ele proporciona!

essa doeu :slight_smile: , foi direto na alma :smiley:

a gente só esta tentando fazer uma consulta normal para partir para o ~* que é próprio do Postresql :smiley:
entendeu amigo,

gomesrod

Bom, espero que vc tenha entendido que não tive nenhuma intenção de ser grosseiro, né! :slight_smile:

Agora de volta ao assunto:
De fato, o operador ~* é mais poderoso que um simples LIKE, pelo fato de ele fazer casamento de expressões regulares. Mas nesse caso, como você só quer verificar se contém a sequência desejada (não está usando recursos específicos de expressão regular), o like pode servir perfeitamente.

Só não esqueça dos curingas % antes e depois da palavra. Assim

// Query JPQL = SELECT a FROM Area a WHERE a.descricao like :descricao query.setParameter("descricao", "%" + descricao + "%");

jaissonduarte

:oops: não, não, não que eu tenha achado “grosseiro”, é que foi engraçado, eu fazendo uma consulta simples para ver se o NativeQuery funcionava e pelo jeito não, :stuck_out_tongue:

pois é como o ~* não funcionou eu desisti dele e estou usando o LIKE que por sinal esta bombando

valeu ao jakefrog que muito me ajudou, ao gomesrod e ao ricardobocchi
obrigado a todos mas eu vou usar o LIKE, fica para próxima o ~* :smiley:

Hebert_Coelho

Senhor jaissonduarte, tudo bem?
Eu sumi daqui pq eu já estava sem saber oq fazer com relação ao seu problema. Geralmente nesses casos eu costumo pesquisar e escrever um post sobre o assunto.

Bem eu estou no momento escrevendo um post sobre JPA e consultas. Diversos modos de se fazer e tals. Vai ter umas 14 páginas! :shock:

Agora, só para botar lenha na fogueira, olha só o que eu acabei de fazer:

Eu mato a cobra e mostro o pau rapaz! :twisted: :twisted: :twisted:

Esse código aí é o código do meu TCC, e que estou utilizando a mesma coisa desse post: Aplicação Web Completa JSF EJB JPA JAAS.
JBoss 7, EJB + JPA.

Veja a versão do seu JDBC, a versão da implementação JPA que você está utilizando. Eu tive um erro bizarro ao declarar @NativeNamedQuery. Tente fazer do mesmo modo que eu postei ai e fale o resultado. :smiley:

jaissonduarte

Criado 3 de abril de 2012
Ultima resposta 14 de abr. de 2012
Respostas 46
Participantes 6