Commit 41bc7ad0b8a45ce69225b88a7ec193b817222518
Exists in
master
Merge branch 'master' of git@github.com:demoiselle/framework.git
Showing
3 changed files
with
103 additions
and
31 deletions
Show diff stats
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(); |