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 | 39 | import java.lang.reflect.Field; |
40 | 40 | import java.util.ArrayList; |
41 | 41 | import java.util.List; |
42 | +import java.util.regex.Matcher; | |
43 | +import java.util.regex.Pattern; | |
42 | 44 | |
43 | 45 | import javax.enterprise.inject.Instance; |
44 | 46 | import javax.inject.Inject; |
... | ... | @@ -48,6 +50,7 @@ import javax.persistence.EntityManager; |
48 | 50 | import javax.persistence.Enumerated; |
49 | 51 | import javax.persistence.Query; |
50 | 52 | import javax.persistence.TransactionRequiredException; |
53 | +import javax.persistence.TypedQuery; | |
51 | 54 | import javax.persistence.criteria.CriteriaBuilder; |
52 | 55 | import javax.persistence.criteria.CriteriaQuery; |
53 | 56 | import javax.persistence.criteria.Predicate; |
... | ... | @@ -159,20 +162,70 @@ public class JPACrud<T, I> implements Crud<T, I> { |
159 | 162 | } |
160 | 163 | |
161 | 164 | @Override |
162 | - @SuppressWarnings("unchecked") | |
163 | 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 | 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 | 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 | 42 | persistence-unit-name-found=Unidade de persist\u00EAncia "{0}" encontrada. |
43 | 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 | 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 | 129 | this.contactDAO.delete(this.contact.getId()); |
130 | 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 | 142 | @Test |
134 | 143 | public void testCountAll() { |
135 | 144 | |
136 | 145 | Pagination pagination = new PaginationImpl(); |
146 | + pagination.setPageSize(10); | |
137 | 147 | PaginationContext actualContext = PowerMock.createMock(PaginationContext.class); |
138 | 148 | expect(actualContext.getPagination(Contact.class)).andReturn(pagination); |
139 | 149 | @SuppressWarnings("unchecked") |
140 | 150 | Instance<PaginationContext> paginationContext = PowerMock.createMock(Instance.class); |
141 | 151 | expect(paginationContext.get()).andReturn(actualContext); |
142 | 152 | setInternalState(this.contactDAO, "paginationContext", paginationContext); |
153 | + | |
154 | + TypedQuery<Contact> typeQuery = makeTypedQuery(); | |
143 | 155 | |
144 | 156 | Query query = EasyMock.createMock(Query.class); |
145 | - expect(query.setFirstResult(EasyMock.anyInt())).andReturn(query); | |
146 | - expect(query.setMaxResults(EasyMock.anyInt())).andReturn(query); | |
147 | 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 | 164 | List<Contact> find = this.contactDAO.findAll(); |
156 | 165 | |
... | ... | @@ -171,11 +180,13 @@ public class JPACrudTest { |
171 | 180 | expect(paginationContext.get()).andReturn(actualContext); |
172 | 181 | setInternalState(this.contactDAO, "paginationContext", paginationContext); |
173 | 182 | |
183 | + TypedQuery<Contact> typeQuery = makeTypedQuery(); | |
184 | + | |
174 | 185 | Query query = EasyMock.createMock(Query.class); |
175 | 186 | |
176 | 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 | 191 | replayAll(query, this.entityManager, paginationContext); |
181 | 192 | |
... | ... | @@ -280,27 +291,31 @@ public class JPACrudTest { |
280 | 291 | |
281 | 292 | @Test |
282 | 293 | public void testFindAll() { |
283 | - | |
294 | + | |
295 | + Pagination pagination = new PaginationImpl(); | |
296 | + pagination.setPageSize(10); | |
284 | 297 | PaginationContext actualContext = PowerMock.createMock(PaginationContext.class); |
285 | - expect(actualContext.getPagination(Contact.class)).andReturn(null); | |
298 | + expect(actualContext.getPagination(Contact.class)).andReturn(pagination); | |
286 | 299 | @SuppressWarnings("unchecked") |
287 | 300 | Instance<PaginationContext> paginationContext = PowerMock.createMock(Instance.class); |
288 | 301 | expect(paginationContext.get()).andReturn(actualContext); |
289 | 302 | setInternalState(this.contactDAO, "paginationContext", paginationContext); |
303 | + | |
304 | + TypedQuery<Contact> typeQuery = makeTypedQuery(); | |
290 | 305 | |
291 | 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 | 314 | List<Contact> find = this.contactDAO.findAll(); |
300 | 315 | |
301 | 316 | assertEquals(1, find.size()); |
302 | 317 | assertTrue(find.iterator().next().getId().equals(1L)); |
303 | - | |
318 | + | |
304 | 319 | verifyAll(); |
305 | 320 | } |
306 | 321 | |
... | ... | @@ -313,12 +328,15 @@ public class JPACrudTest { |
313 | 328 | Instance<PaginationContext> paginationContext = PowerMock.createMock(Instance.class); |
314 | 329 | expect(paginationContext.get()).andReturn(actualContext); |
315 | 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 | 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 | 341 | try { |
324 | 342 | this.contactDAO.findAll(); | ... | ... |