Agrupaciones en consultas con javax.persistence.criteria.CriteriaBuilder
Vamos a poner un par de ejemplos de uso del CriteriaBuilder en JPA para poder hacer consultas usando JpaSpecificationExecutor e incluso usar agrupaciones con groupBy.
Se van a ir poniendo las diferentes clases desde el Entity hasta el Service:
Entity de la tabla cuenta con un par de campos.
@Entity(name="cuentaEntity")
@Table(name="CUENTA")
public class CuentaEntity implements Serializable {
@Id
private Integer id;
@Column(name="balance")
private Integer balance;
@Column(name="empresa")
private String empresa;
@Column(name="fecha")
@Temporal(TemporalType.TIMESTAMP)
private Date fecha;
//getter setter
}
Su correspondiente JPAMetalModelEntityProcessor, la vamos a utilizar para las consultas.
@Generated(value = "org.hibernate.jpamodelgen.JPAMetalModelEntityProcessor")
@StaticMetamodel(CuentaEntity.class)
public abstract class CuentaEntity_ {
public static volatile SingularAttribute< CuentaEntity, Integer> id;
public static volatile SingularAttribute< CuentaEntity, Integer> balance;
public static volatile SingularAttribute< CuentaEntity, String> empresa;
public static volatile SingularAttribute< CuentaEntity, Date> fecha;
}
Un clase repositorio. Hay que hacer que herede tanto de la JpaRepository como del JpaSpecificationExecutor.
@Repository
public interface CuentaRepository extends JpaRepository< CuentaEntity, Integer>,
JpaSpecificationExecutor< CuentaEntity> {
}
Creamos nuestra clase criteria donde meteremos las especificaciones de las querys. Se añaden unos ejemplos de condicionales
public class CuentaCriteria implements Serializable{
private Integer id;
private Integer balance;
private String empresa;
private Date fecha;
......
public static Specification< CuentaEntity> search(final CuentaCriteria cri){
return new Specification< CuentaEntity>(){
@Override
public Predicate toPredicate(Root< CuentaEntity> root,
CriteriaQuery< ?> criQuery, CriteriaBuilder criBuilder) {
List< Predicate> predicates = new ArrayList< Predicate>();
//el nombre de la empresa sea igual al que se pasa en CuentaCriteria. Si no está vacia.
if( !StringUtils.isEmpty( cri.getEmpresa())){
predicates.add( criBuilder.like(root.get(CuentaEntity_.empresa), cri.getEmpresa()) );
}
//la fecha debe ser igual a la que se pasa en CuentaCriteria. Si no está vacia.
if( !StringUtils.isEmpty( cri.getFecha())){
predicates.add( criBuilder.equal(root.get(StatementEntity_.fecha),cri.getFecha()) );
}
//podemos añadir tambien una condicion de tipo OR ( id = 0 OR id = 1).
List< Predicate> predOr = new ArrayList< Predicate>();
predOr.add( criBuilder.equal(root.get(CuentaEntity_.id), 0) );
predOr.add( criBuilder.equal(root.get(CuentaEntity_.id), 1) );
predicates.add( criBuilder.or(predOr.toArray(new Predicate[predOr.size()]) ) );
//Si tubieramos un objeto Embeddable u otro tipo de objeto podriamos acceder
//a las propiedades de ese objeto
//predicates.add( criBuilder.like(root.get("OBJETO").get("CAMPO_OBJETO"), "qqqqqq") );
..............
//Concatenamos todos los predicados como ands
return criBuilder.and(predicates.toArray(new Predicate[predicates.size()]));
}
};
}
}
Interfaz con nuestro servicio con unos métodos de prueba.
public interface CuentaService{
public Page< CuentaEntity> find(CuentaCriteria criteria, Pageable pageable);
public List< Object[]> findGroupBy(CuentaCriteria criteria);
public Long count(CuentaCriteria criteria);
.........
}
Y su implementación:
@Component("cuentaService")
@Transactional
public class CuentaServiceImpl implements CuentaService {
@PersistenceContext
EntityManager em;
@Autowired
private CuentaRepository cuentaRepository;
//En este método permite realizar una consulta que devuelve el listado de todas las cuentas que
//lo cumplen. Las condiciones de la consulta se le pasan con CuentaCriteria.search(criteria).
//No devolverá todos los elementos al pasarle un objeto Pageable para paginación.
public Page< CuentaEntity> find(CuentaCriteria criteria, Pageable pageable){
return cuentaRepository.findAll( CuentaCriteria.search(criteria), pageable);
}
//En este método deveulve la cuenta de la consulta anterior. Las condiciones de la consulta
//se le pasan con CuentaCriteria.search(criteria).
public Long count(StatementCriteria criteria){
return this.statementRepository.count( StatementCriteria.search(criteria) );
}
//El groupBy no funciona bien si se mete en StatementCriteria.search(criteria), eso es porque
//aunque hagas un multiselect() con sólo los elementos que quieres sacar en la consulta te lo va
//a sobreescribir por el select().
//Una posible solución sería hacerlo como se hace en este método.
public List< Object[]> findGroupBy(CuentaCriteria criteria){
CriteriaBuilder cb = em.getCriteriaBuilder();
CriteriaQuery> cq = cb.createQuery();
Root root = cq.from(StatementEntity.class);
//declaramos el multiselect con las columnas a devolver
cq.multiselect(
//fecha mayor
cb.greatest( root.get(CuentaEntity_.fecha).as(java.util.Date.class) ),
//fecha menor
cb.least( root.get(CuentaEntity_.fecha).as(java.util.Date.class) ),
//balance mayor
cb.max( root.get(CuentaEntity_.balance) ),
//balance menor
cb.min( root.get(CuentaEntity_.balance) ),
//media del balance
cb.avg( root.get(CuentaEntity_.balance) ),
//suma del balance total
cb.sum( root.get(CuentaEntity_.balance).as(java.lang.Integer.class) ),
//suma del balance siempre que sea mayor de cero, es decir, positivo
cb.sum( cb.selectCase()
.when(cb.greaterThan(root.get(CuentaEntity_.balance), 0),
root.get(CuentaEntity_.balance) ).otherwise(0)),
//contador con todas las filas agrupadas
cb.count( root.get(CuentaEntity_.id) )
);
//aplicamos todas la condiciones de consulta al where
cq.where( CuentaCriteria.search(criteria).toPredicate(root, cq, cb) );
//le decimos que agrupe por el nombre de las empresas
cq.groupBy( root.get( CuentaEntity_.empresa) );
Query query = em.createQuery(cq);
//Por último lo podemos retornar como una lista de objetos
return (List< Object[]>)query.getResultList();
}
}
Categorias
- adobe (2)
- agile (1)
- Alfresco (1)
- Android (26)
- Angular (6)
- angularjs (10)
- apache (1)
- axis (2)
- Bases de datos (14)
- Bootstrap (1)
- C# (3)
- Cámara (1)
- chrome (3)
- Codeigniter (2)
- Control de Versiones (2)
- CSS (25)
- CVS (1)
- Django (9)
- Django Rest Framework (1)
- DNS (1)
- Docker (3)
- dominio (1)
- eclipse (5)
- Entity Framework (2)
- ETL (1)
- Firefox (6)
- flash (1)
- freecad (1)
- Git (12)
- GitHub (4)
- gpg (2)
- Groovy (1)
- Handlebars (1)
- hibernate (4)
- hosting (1)
- HTML (50)
- HTML 5 (26)
- Impresión 3D (9)
- Inkscape (1)
- IOS (2)
- ireports (3)
- Java (44)
- Javascript (55)
- JBoss (5)
- JPA (2)
- JQuery (20)
- Json (7)
- JSP (6)
- Keycloak (1)
- Lamp (1)
- LDAP (2)
- lean (1)
- linkedin (1)
- LINQ (1)
- linux (13)
- Livecycle (1)
- log (1)
- microcontroladores (1)
- MongoDB (4)
- MySQL (8)
- Node.js (5)
- OC4J (1)
- Openshift (2)
- Oracle (6)
- Patrones de Diseño (1)
- Photoshop (2)
- php (20)
- PostgreSQL (1)
- python (19)
- rabbitmq (1)
- Raspberry PI (13)
- Raspherry PI (5)
- React (6)
- seguridad (3)
- Selenium (3)
- Sencha Touch (1)
- Sin categoría (29)
- Spring (17)
- spring-boot (3)
- SQL (7)
- SQLServer (1)
- SSO (1)
- struts (2)
- SVN (1)
- Talend (1)
- Tomcat (6)
- unity (3)
- Visual Studio Code (2)
- vmware (5)
- Web Services (11)
- windows (18)
- wordpress (10)
- Xiaomi (1)
- xml (2)
Trabajos Realizados
- App Android – Autoka Fr
- App Android – Cartelera Cántabra
- App Android – Gramática y Vocabulario Ingles
- App Android – Hoja de Gastos
- App Android – Hotel Torre Cristina
- App Android – OcioEnjoy
- App Android – Visor CardBoard
- App Firefox – Managapp
- DiamanteBomba – DisasterCode
- Generador de Partes de Trabajo
- GitHub – Android Web Generator
- GitHub – Dynamic Angular Gallery
- GitHub – Dynamic React Gallery
- GitHub – Sotilizator
- GitHub – SpringAngularJS
- GitHub – Swiper Dynamic Angular Gallery
- HazParejas – DisasterCode
- RompeCabezas – DisasterCode
- Unity Game – English Couple
- Unity Game – Kill Wasp
- WordPress – El Buen Apicultor
- WordPress – El Cajón de los Retales
- WordPress – El Vestidito Azul
- WordPress – Feuchas
- WordPress – Fragua de Navajas Ponce
- WordPress – Humor a las Tres
- WordPress – Photo Places


