Commit 1279fa3443845a8c1500b16ae8d19950cde583cd

Authored by Wilson Guimarães
2 parents 1f211e0a 3d6f570a
Exists in master

Merge pull request #13 from botelhojp/master

Inclusão de Consulta JPQL e CriteriaQuery Genérica ao JPACrud
impl/extension/jpa/src/main/java/br/gov/frameworkdemoiselle/template/JPACrud.java
@@ -39,6 +39,8 @@ package br.gov.frameworkdemoiselle.template; @@ -39,6 +39,8 @@ package br.gov.frameworkdemoiselle.template;
39 import java.lang.reflect.Field; 39 import java.lang.reflect.Field;
40 import java.util.ArrayList; 40 import java.util.ArrayList;
41 import java.util.List; 41 import java.util.List;
  42 +import java.util.regex.Matcher;
  43 +import java.util.regex.Pattern;
42 44
43 import javax.enterprise.inject.Instance; 45 import javax.enterprise.inject.Instance;
44 import javax.inject.Inject; 46 import javax.inject.Inject;
@@ -48,6 +50,7 @@ import javax.persistence.EntityManager; @@ -48,6 +50,7 @@ import javax.persistence.EntityManager;
48 import javax.persistence.Enumerated; 50 import javax.persistence.Enumerated;
49 import javax.persistence.Query; 51 import javax.persistence.Query;
50 import javax.persistence.TransactionRequiredException; 52 import javax.persistence.TransactionRequiredException;
  53 +import javax.persistence.TypedQuery;
51 import javax.persistence.criteria.CriteriaBuilder; 54 import javax.persistence.criteria.CriteriaBuilder;
52 import javax.persistence.criteria.CriteriaQuery; 55 import javax.persistence.criteria.CriteriaQuery;
53 import javax.persistence.criteria.Predicate; 56 import javax.persistence.criteria.Predicate;
@@ -159,20 +162,70 @@ public class JPACrud<T, I> implements Crud<T, I> { @@ -159,20 +162,70 @@ public class JPACrud<T, I> implements Crud<T, I> {
159 } 162 }
160 163
161 @Override 164 @Override
162 - @SuppressWarnings("unchecked")  
163 public List<T> findAll() { 165 public List<T> findAll() {
164 - final String jpql = "select this from " + getBeanClass().getSimpleName() + " this";  
165 - final Query query = getEntityManager().createQuery(jpql); 166 + return findByJPQL("select this from " + getBeanClass().getSimpleName() + " this");
  167 + }
166 168
167 - final Pagination pagination = getPagination(); 169 + /**
  170 + * Search JPQL integrated into the context of paging
  171 + * @param jpql - query in syntax JPQL
  172 + * @return a list of entities
  173 + */
  174 + protected List<T> findByJPQL(String jpql) {
  175 + pagination = getPagination();
  176 + TypedQuery<T> listQuery = getEntityManager().createQuery(jpql, getBeanClass());
168 if (pagination != null) { 177 if (pagination != null) {
169 - pagination.setTotalResults(this.countAll().intValue());  
170 - query.setFirstResult(pagination.getFirstResult());  
171 - query.setMaxResults(pagination.getPageSize()); 178 + String countQueryString = createCountQueryString(jpql);
  179 + Query query = getEntityManager().createQuery(countQueryString);
  180 + Number cResults = (Number) query.getSingleResult();
  181 + pagination.setTotalResults(cResults.intValue());
  182 + listQuery.setFirstResult(pagination.getFirstResult());
  183 + listQuery.setMaxResults(pagination.getPageSize());
172 } 184 }
  185 + return listQuery.getResultList();
  186 + }
173 187
174 - List<T> lista = query.getResultList();  
175 - return lista; 188 + /**
  189 + * Search CriteriaQuery integrated into the context of paging
  190 + * @param criteriaQuery - structure CriteriaQuery
  191 + * @return a list of entities
  192 + */
  193 + public List<T> findByCriteriaQuery(CriteriaQuery<T> criteriaQuery) {
  194 + pagination = getPagination();
  195 + TypedQuery<T> listQuery = getEntityManager().createQuery(criteriaQuery);
  196 + if (pagination != null) {
  197 + CriteriaBuilder builder = getEntityManager().getCriteriaBuilder();
  198 + CriteriaQuery<Long> countQuery = builder.createQuery(Long.class);
  199 + countQuery.select(builder.count(countQuery.from(getBeanClass())));
  200 + countQuery.where(criteriaQuery.getRestriction());
  201 + getEntityManager().createQuery(countQuery);
  202 + pagination.setTotalResults((int) (getEntityManager().createQuery(countQuery).getSingleResult() + 0));
  203 + listQuery.setFirstResult(pagination.getFirstResult());
  204 + listQuery.setMaxResults(pagination.getPageSize());
  205 + }
  206 + return listQuery.getResultList();
  207 + }
  208 +
  209 + /**
  210 + * Converts JPA query to JPA count query
  211 + * @param query
  212 + * @return
  213 + */
  214 + private String createCountQueryString(String query) {
  215 + query = query.toUpperCase();
  216 + Matcher matcher = Pattern.compile("SELECT(.+)FROM").matcher(query);
  217 + if (matcher.find()){
  218 + String group = matcher.group(1).trim();
  219 + query = query.replaceFirst(group, "COUNT(" + group + ")");
  220 + matcher = Pattern.compile("ORDER(.+)").matcher(query);
  221 + if (matcher.find()){
  222 + group = matcher.group(1);
  223 + query = query.replaceFirst("ORDER"+group, "");
  224 + }
  225 + return query;
  226 + }else{
  227 + throw new DemoiselleException(bundle.get().getString("malformed-jpql"));
  228 + }
176 } 229 }
177 230
178 /** 231 /**
impl/extension/jpa/src/main/resources/demoiselle-jpa-bundle.properties
@@ -41,4 +41,5 @@ can-not-get-persistence-unit-from-persistence=N\u00E3o foi poss\u00EDvel obter a @@ -41,4 +41,5 @@ can-not-get-persistence-unit-from-persistence=N\u00E3o foi poss\u00EDvel obter a
41 more-than-one-persistence-unit-defined=Existe mais de uma unidade de persist\u00EAncia definida. Utilize @{0} no ponto de inje\u00E7\u00E3o ou defina o atributo "frameworkdemoiselle.persistence.unit.name" no arquivo demoiselle.properties. 41 more-than-one-persistence-unit-defined=Existe mais de uma unidade de persist\u00EAncia definida. Utilize @{0} no ponto de inje\u00E7\u00E3o ou defina o atributo "frameworkdemoiselle.persistence.unit.name" no arquivo demoiselle.properties.
42 persistence-unit-name-found=Unidade de persist\u00EAncia "{0}" encontrada. 42 persistence-unit-name-found=Unidade de persist\u00EAncia "{0}" encontrada.
43 entity-manager-closed=O gerenciador de entidades foi fechado. 43 entity-manager-closed=O gerenciador de entidades foi fechado.
44 -no-transaction-active=Nenhuma transa\u00E7\u00E3o est\u00E1 ativa, verifique a configura\u00E7\u00E3o "{0}" no arquivo "{1}" e defina a sua estrat\u00E9gia de transa\u00E7\u00E3o.  
45 \ No newline at end of file 44 \ No newline at end of file
  45 +no-transaction-active=Nenhuma transa\u00E7\u00E3o est\u00E1 ativa, verifique a configura\u00E7\u00E3o "{0}" no arquivo "{1}" e defina a sua estrat\u00E9gia de transa\u00E7\u00E3o.
  46 +malformed-jpql=Consulta JPQL mal formada para pagina\u00E7\u00E3o de dados.
impl/extension/jpa/src/test/java/br/gov/frameworkdemoiselle/template/JPACrudTest.java
@@ -129,28 +129,37 @@ public class JPACrudTest { @@ -129,28 +129,37 @@ public class JPACrudTest {
129 this.contactDAO.delete(this.contact.getId()); 129 this.contactDAO.delete(this.contact.getId());
130 verify(this.entityManager); 130 verify(this.entityManager);
131 } 131 }
132 - 132 +
  133 + private TypedQuery<Contact> makeTypedQuery() {
  134 + @SuppressWarnings("unchecked")
  135 + TypedQuery<Contact> typeQuery = EasyMock.createMock(TypedQuery.class);
  136 + expect(typeQuery.setFirstResult(EasyMock.anyInt())).andReturn(null);
  137 + expect(typeQuery.setMaxResults(EasyMock.anyInt())).andReturn(null);
  138 + expect(typeQuery.getResultList()).andReturn(createContacts(1));
  139 + return typeQuery;
  140 + }
  141 +
133 @Test 142 @Test
134 public void testCountAll() { 143 public void testCountAll() {
135 144
136 Pagination pagination = new PaginationImpl(); 145 Pagination pagination = new PaginationImpl();
  146 + pagination.setPageSize(10);
137 PaginationContext actualContext = PowerMock.createMock(PaginationContext.class); 147 PaginationContext actualContext = PowerMock.createMock(PaginationContext.class);
138 expect(actualContext.getPagination(Contact.class)).andReturn(pagination); 148 expect(actualContext.getPagination(Contact.class)).andReturn(pagination);
139 @SuppressWarnings("unchecked") 149 @SuppressWarnings("unchecked")
140 Instance<PaginationContext> paginationContext = PowerMock.createMock(Instance.class); 150 Instance<PaginationContext> paginationContext = PowerMock.createMock(Instance.class);
141 expect(paginationContext.get()).andReturn(actualContext); 151 expect(paginationContext.get()).andReturn(actualContext);
142 setInternalState(this.contactDAO, "paginationContext", paginationContext); 152 setInternalState(this.contactDAO, "paginationContext", paginationContext);
  153 +
  154 + TypedQuery<Contact> typeQuery = makeTypedQuery();
143 155
144 Query query = EasyMock.createMock(Query.class); 156 Query query = EasyMock.createMock(Query.class);
145 - expect(query.setFirstResult(EasyMock.anyInt())).andReturn(query);  
146 - expect(query.setMaxResults(EasyMock.anyInt())).andReturn(query);  
147 expect(query.getSingleResult()).andReturn(10L); 157 expect(query.getSingleResult()).andReturn(10L);
  158 +
  159 + expect(this.entityManager.createQuery("select this from Contact this", Contact.class)).andReturn(typeQuery);
  160 + expect(this.entityManager.createQuery("SELECT COUNT(THIS) FROM CONTACT THIS")).andReturn(query);
148 161
149 - expect(this.entityManager.createQuery("select this from Contact this")).andReturn(query);  
150 - expect(this.entityManager.createQuery("select count(this) from Contact this")).andReturn(query);  
151 - expect(query.getResultList()).andReturn(createContacts(1));  
152 -  
153 - replayAll(query, this.entityManager, paginationContext); 162 + replayAll(typeQuery, query, this.entityManager, paginationContext);
154 163
155 List<Contact> find = this.contactDAO.findAll(); 164 List<Contact> find = this.contactDAO.findAll();
156 165
@@ -171,11 +180,13 @@ public class JPACrudTest { @@ -171,11 +180,13 @@ public class JPACrudTest {
171 expect(paginationContext.get()).andReturn(actualContext); 180 expect(paginationContext.get()).andReturn(actualContext);
172 setInternalState(this.contactDAO, "paginationContext", paginationContext); 181 setInternalState(this.contactDAO, "paginationContext", paginationContext);
173 182
  183 + TypedQuery<Contact> typeQuery = makeTypedQuery();
  184 +
174 Query query = EasyMock.createMock(Query.class); 185 Query query = EasyMock.createMock(Query.class);
175 186
176 expect(query.getSingleResult()).andThrow(new DemoiselleException("")); 187 expect(query.getSingleResult()).andThrow(new DemoiselleException(""));
177 - expect(this.entityManager.createQuery("select this from Contact this")).andReturn(query);  
178 - expect(this.entityManager.createQuery("select count(this) from Contact this")).andReturn(query); 188 + expect(this.entityManager.createQuery("select this from Contact this", Contact.class)).andReturn(typeQuery);
  189 + expect(this.entityManager.createQuery("SELECT COUNT(THIS) FROM CONTACT THIS")).andReturn(query);
179 190
180 replayAll(query, this.entityManager, paginationContext); 191 replayAll(query, this.entityManager, paginationContext);
181 192
@@ -280,27 +291,31 @@ public class JPACrudTest { @@ -280,27 +291,31 @@ public class JPACrudTest {
280 291
281 @Test 292 @Test
282 public void testFindAll() { 293 public void testFindAll() {
283 - 294 +
  295 + Pagination pagination = new PaginationImpl();
  296 + pagination.setPageSize(10);
284 PaginationContext actualContext = PowerMock.createMock(PaginationContext.class); 297 PaginationContext actualContext = PowerMock.createMock(PaginationContext.class);
285 - expect(actualContext.getPagination(Contact.class)).andReturn(null); 298 + expect(actualContext.getPagination(Contact.class)).andReturn(pagination);
286 @SuppressWarnings("unchecked") 299 @SuppressWarnings("unchecked")
287 Instance<PaginationContext> paginationContext = PowerMock.createMock(Instance.class); 300 Instance<PaginationContext> paginationContext = PowerMock.createMock(Instance.class);
288 expect(paginationContext.get()).andReturn(actualContext); 301 expect(paginationContext.get()).andReturn(actualContext);
289 setInternalState(this.contactDAO, "paginationContext", paginationContext); 302 setInternalState(this.contactDAO, "paginationContext", paginationContext);
  303 +
  304 + TypedQuery<Contact> typeQuery = makeTypedQuery();
290 305
291 Query query = EasyMock.createMock(Query.class); 306 Query query = EasyMock.createMock(Query.class);
292 - // expect(query.setFirstResult(EasyMock.anyInt())).andReturn(query);  
293 - // expect(query.setMaxResults(EasyMock.anyInt())).andReturn(query);  
294 - expect(this.entityManager.createQuery("select this from Contact this")).andReturn(query);  
295 - expect(query.getResultList()).andReturn(createContacts(1)); 307 + expect(query.getSingleResult()).andReturn(10L);
  308 +
  309 + expect(this.entityManager.createQuery("select this from Contact this", Contact.class)).andReturn(typeQuery);
  310 + expect(this.entityManager.createQuery("SELECT COUNT(THIS) FROM CONTACT THIS")).andReturn(query);
296 311
297 - replayAll(query, this.entityManager, paginationContext); 312 + replayAll(typeQuery, query, this.entityManager, paginationContext);
298 313
299 List<Contact> find = this.contactDAO.findAll(); 314 List<Contact> find = this.contactDAO.findAll();
300 315
301 assertEquals(1, find.size()); 316 assertEquals(1, find.size());
302 assertTrue(find.iterator().next().getId().equals(1L)); 317 assertTrue(find.iterator().next().getId().equals(1L));
303 - 318 +
304 verifyAll(); 319 verifyAll();
305 } 320 }
306 321
@@ -313,12 +328,15 @@ public class JPACrudTest { @@ -313,12 +328,15 @@ public class JPACrudTest {
313 Instance<PaginationContext> paginationContext = PowerMock.createMock(Instance.class); 328 Instance<PaginationContext> paginationContext = PowerMock.createMock(Instance.class);
314 expect(paginationContext.get()).andReturn(actualContext); 329 expect(paginationContext.get()).andReturn(actualContext);
315 setInternalState(this.contactDAO, "paginationContext", paginationContext); 330 setInternalState(this.contactDAO, "paginationContext", paginationContext);
  331 +
  332 + @SuppressWarnings("unchecked")
  333 + TypedQuery<Contact> typeQuery = EasyMock.createMock(TypedQuery.class);
  334 + expect(typeQuery.getResultList()).andThrow(new DemoiselleException(""));
316 335
317 Query query = EasyMock.createMock(Query.class); 336 Query query = EasyMock.createMock(Query.class);
318 - expect(this.entityManager.createQuery("select this from Contact this")).andReturn(query);  
319 - expect(query.getResultList()).andThrow(new DemoiselleException("")); 337 + expect(this.entityManager.createQuery("select this from Contact this", Contact.class)).andReturn(typeQuery);
320 338
321 - replayAll(query, this.entityManager, paginationContext); 339 + replayAll(typeQuery, query, this.entityManager, paginationContext);
322 340
323 try { 341 try {
324 this.contactDAO.findAll(); 342 this.contactDAO.findAll();