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(); Rootroot = 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