Que lista todos registros, porém, eu gostaria de criar outro método que fizesse assim:
public List<T> findByName(String nome) {
javax.persistence.criteria.CriteriaQuery cq = getEntityManager().getCriteriaBuilder().createQuery();
cq.select(cq.from(entityClass));
//Aqui é a zebra...
//cq.select(cq.where("nome like '%"+nome+"%'"));
//sei que não é assim não dá.
return getEntityManager().createQuery(cq).getResultList();
}
Como eu posso implementar esse meu where ?
Estou usando JPA e EclipseLink.
Supondo q vc tenha em seu projeto uma entidade Person:
public class PersonDAO {
@Inject EntityManager em;
public List<Person> findByName(String name) {
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery<Person> cq = cb.createQuery(Person.class);
Root<Person> f = cq.from(Person.class);
cq.where(cb.like(f.get(Person_.nome, "%" + name + "%")));
return em.createQuery(cq).getResultList();
}
}
Lembre-se tb de adicionar o metamodel Person_ no mesmo pacote de Person.
@StaticMetamodel(Person.class)
public class Person_ {
public static volatile SingularAttribute<Person, Long> id;
public static volatile SingularAttribute<Person, String> name;
// adicione os demais atributos de Person tb.
}
Da p/ vc ver q o código é bastante volumoso de maneira q é preferível q vc use NamedQueries. NamedQueries são mais simples e dispensam o padrão DAO, ou seja, é um artefato a menos p/ vc gerar quando estiver programando. Use CriteriaQueries apenas quando vc precisar criar queries dinâmicamente, tipo, quando vc tiver um formulário como aquele formulário de busca avançada do google com um montão de campos e vc precisar montar uma busca com apenas os campos preenchidos pelo usuário. O uso de CriteriaQueries viola o princípio KISS.
[quote=dev.rafael]
…
Da p/ vc ver q o código é bastante volumoso de maneira q é preferível q vc use NamedQueries. NamedQueries são mais simples e dispensam o padrão DAO, ou seja, é um artefato a menos p/ vc gerar quando estiver programando. Use CriteriaQueries apenas quando vc precisar criar queries dinâmicamente, tipo, quando vc tiver um formulário como aquele formulário de busca avançada do google com um montão de campos e vc precisar montar uma busca com apenas os campos preenchidos pelo usuário. O uso de CriteriaQueries viola o princípio KISS.[/quote]
Poxa, eu achei que tava muito complicado mesmo…
To tentando usar NamedQueries…
Na classe contato, criei a anotação
@NamedQueries(@NamedQuery(name="bean.findByNAme",query="select c.* from contato c where c.nome like :nome"))
Alterei o meu método para:
public List<T> findByName(String nome) {
Query query= getEntityManager().createNamedQuery("bean.findByName");
nome = "%"+nome+"%";
query.setParameter("nome",nome);
return query.getResultList();
}
porém, estou recendo o erro:
Caused by: Exception [EclipseLink-8025] (Eclipse Persistence Services - 2.0.1.v20100213-r6600): org.eclipse.persistence.exceptions.JPQLException
Exception Description: Syntax error parsing the query [bean.findByNAme: select c.* from contato c where c.nome like :nome], line 1, column 9: unexpected token [*].
Escrevi o select como seria no banco… Tá errado ? Como é o certo?
@NamedQueries({
@NamedQuery(name = Bean.BY_NAME, query = "select c from contato c where c.nome like :nome")
})
public class Bean {
public static final String BY_NAME = "Bean.byName";
}
Como no código assim, prefira constantes ao invés de strings literais p/ nomes de suas namedqueries. Outra coisa, não crie DAOs. Com as namedqueries o EntityManager ganha um interface de DAO genérico.
@Named
public class BeanController {
@Inject EntityManager em;
private String name;
public String getName() { return name; }
public void setName(String name) { this.name = name; }
public List<Bean> getBeans() {
return em.createNamedQuery(Bean.BY_NAME, Bean.class)
.setParameter("name", name)
.getResultList();
}
}
Criar uma classe dedicada a execução de NamedQueries é um tanto quando overengineering.
Não entendi muito bem :oops:
Eu devo criar uma Classe Bean e colocar todas NamedQueryes nela ?
Devo também criar uma Classe BeanController para fazer a chamada à classe Bean ?
Mesmo sem entender direito, consegui fazer o código anterior funcionar. O meu erro estava no “*” e no “from contato”, quando deveria ser “from Contato”.
Mais uma dúvida no mesmo assunto… coloquei o comando “like”, mas eu gostaria de usar o ilike do postgresql, para não considerar case sensitive. Tem como ?
[quote=dev.rafael]Não! O JPA não suporta nada como o ILIKE. O q vc pode fazer é:
lower(b.name) like lower(%dev%)
[/quote]
Num dá… eu tinha tentado com upper, agora tentei com o lower…
e o erro reportado
…
Caused by: Exception [EclipseLink-8025] (Eclipse Persistence Services - 2.0.1.v20100213-r6600): org.eclipse.persistence.exceptions.JPQLException
Exception Description: Syntax error parsing the query [bean.findByName: select c from Contato c where lower(c.nome) like lower(:nome)], line 1, column 49: unexpected token [lower].
…
assim @NamedQuery(name=“bean.findByName”,query=“select c from Contato c where UPPER(c.nome) like :nome”))
funciona… fiz o parametro passado para a função ser modificado também, aí deu certo.