-
Notifications
You must be signed in to change notification settings - Fork 3
Repository
Com o objetivo de facilitar e reutilizar código de persistência para as entidades, disponibilizou-se três suportes possíveis:
As operações de manipulação de entidades utilizando JPA são encapsuladas em duas classes
Essa classe serve como suporte para que o desenvolvedor possa especializar a persistência para cada entidade. É possível, por exemplo, criar uma PessoaService herdando de EntityRepository e reaproveitar vários métodos de persistência dessa entidade, dando a comodidade ao desenvolvedor de implementar apenas as operações específicas que desejar.
Dentre as diversas operações providas, temos:
/**
* Persist (new entity) or merge the given entity. The distinction on calling either
* method is done based on the primary key field being null or not.
* If this results in wrong behavior for a specific case, consider using the
* {@link org.apache.deltaspike.data.api.EntityManagerDelegate} which offers both
* {@code persist} and {@code merge}.
* @param entity Entity to save.
* @return Returns the modified entity.
*/
public E save(E entity){
if (EntityUtil.isNew(entityManager, entity)){
entityManager.persist(entity);
return entity;
}
return entityManager.merge(entity);
}
/**
* Convenience access to {@link javax.persistence.EntityManager#remove(Object)}.
* @param entity Entity to remove.
*/
public void remove(E entity){
entityManager.remove(contains(entity) ? entity : entityManager.merge(entity));
}
/**
* Convenience access to {@link javax.persistence.EntityManager#refresh(Object)}.
* @param entity Entity to refresh.
*/
public void refresh(E entity){
entityManager.refresh(entity);
}
/**
* Remove the given entity from the persistence context, causing
* a managed entity to become detached. Unflushed changes made
* to the entity if any (including removal of the entity),
* will not be synchronized to the database. Entities which
* previously referenced the detached entity will continue to
* reference it.
* @param entity entity instance
* @throws IllegalArgumentException if the instance is not an entity
*/
public void detach(E entity) {
entityManager.detach(entity);
}
/**
* Entity lookup by primary key. Convenicence method around
* {@link javax.persistence.EntityManager#find(Class, Object)}.
* @param primaryKey DB primary key.
* @return Entity identified by primary or null if it does not exist.
*/
public E findBy(PK primaryKey){
return entityManager.find(type, primaryKey);
}
/**
* Lookup all existing entities of entity class {@code <E>}.
* @return List of entities, empty if none found.
*/
public List<E> findAll(){
return jpql().from(EntityUtil.getEntityName(entityManager, type)).getResultList(type);
}
/**
* Find entities by the given named query.
* @param namedQuery Named Query
* @param params Named Query parameters
* @return List of entities, empty if none found.
*/
public List<E> findByNamedQuery(String namedQuery, Map<String, Object> params){
TypedQuery<E> query = entityManager.createNamedQuery(namedQuery, type);
if(params != null){
for(String paramName : params.keySet()){
query.setParameter(paramName, params.get(paramName));
}
}
return query.getResultList();
}
/**
* Find single entity by the given named query.
* @param namedQuery Named Query
* @param params Named Query parameters
* @return Entity
*/
public E findUniqueByNamedQuery(String namedQuery, Map<String, Object> params){
TypedQuery<E> query = entityManager.createNamedQuery(namedQuery, type);
if(params != null){
for(String paramName : params.keySet()){
query.setParameter(paramName, params.get(paramName));
}
}
return query.getSingleResult();
}A classe JPQL serve como suporte para a construção de queries utilizando a Java Persistence Query Language. Para isso, o construtor dessa classe deve receber o entityManager para que, ao final da configuração, ela possa executar a query.
A configuração da query será feita orientada a objeto e de maneira simular a uma Criteria, mas que construí uma JPQL com trechos de código para especificar o que será incluído no:
- select;
- from;
- where;
- group by;
- order by;
- range de resultado.
Ao final da configuração, os resultados podem ser obtidos em lista ou por um resultado único.
/**
* Retorna uma lista de entidades que atendem aos critérios da busca.
* Já faz o <code>cast</code> para a classe <code>resultType</code> passada.
*
* @param resultType
* @return
*/
@SuppressWarnings("unchecked")
public <T> List<T> getResultList(Class<T> resultType);
/**
* Retorna uma lista de entidades que atendem aos critérios da busca.
*
* @return
*/
public List<?> getResultList();
/**
* Retorna uma única entidade que atenda aos critérios da busca.
* Já faz o <code>cast</code> para a classe <code>resultType</code> passada.
*
* @param resultType
* @return
*/
@SuppressWarnings("unchecked")
public <T> T getSingleResult(Class<T> resultType);
/**
* Retorna uma única entidade que atenda aos critérios da busca.
*
* @return
*/
public Object getSingleResult();
/**
* Retorna uma única entidade que atenda aos critérios da busca.
* Trata o caso de não haver resultado, retornando <code>null</code>.
* Já faz o <code>cast</code> para a classe <code>resultType</code> passada.
*
* @param resultType
* @return
*/
@SuppressWarnings("unchecked")
public <T> T getAnyResult(Class<T> resultType);
/**
* Retorna uma única entidade que atenda aos critérios da busca.
* Trata o caso de não haver resultado, retornando <code>null</code>.
*
* @return
*/
public Object getAnyResult();Exemplo de uso em um busca:
public List<Pessoa> findByNome(String nome){
JPQL jpql = jpql().from("Pessoa");
if(StringUtils.isNotBlank(nome)){
jpql.where("nome = :nome").withParam("nome", nome);
}
return jpql.getResultList(Pessoa.class);
}
public boolean isUnique(Pessoa pessoa){
JPQL jpql = jpql().select("count(p)").from("Pessoa p");
jpql.where("(p.cpf = :cpf or p.email = :email)");
jpql.withParam("cpf", pessoa.getCpf());
jpql.withParam("email", pessoa.getEmail());
if(pessoa.getId() != null){
jpql.where("p.id != :id").withParam("id", pessoa.getId());
}
return jpql.getSingleResult(Long.class) == 0;
}Validações são ações necessárias em qualquer sistema que trabalhe sobre um domínio específico de dados. Elas variam de acordo com os tipos de campos utilizados e podem ser específicas a certas regiões.
A API em javax.validation fornece uma série de anotações que permite que os desenvolvedores restringam o conjunto aceitável de dados em um determinado campo. Mas essas validações seguem padrões internacionais, não apresentando soluções para CPF e CNPJ, por exemplo.
O Suri-CDI possui facilidades para trabalhar com esses tipos de dados. O pacote br.com.surittec.suricdi.core.validation contem anotações para que o Java Bean Validation seja capaz de interpretar e validar um determinado campo.
A arquitetura especializa esse comportamento e disponibiliza as validações para os campos de CPF, CNPJ e E-mail da seguinte maneira:
@Cpf
@Column(name = "cpf", length = 11, unique = true, nullable = false)
private String cpf;
@Cnpj
@Column(name = "cnpj", length = 14, unique = true, nullable = false)
private String cnpj;
@Email
@Column(name = "email", length = 100, unique = true, nullable = false)
private String email;© Copyright 2014 SURITTEC