adapt uuidAndTitleCache services and dao methods to search for a pattern
[cdmlib.git] / cdmlib-persistence / src / main / java / eu / etaxonomy / cdm / persistence / dao / hibernate / common / IdentifiableDaoBase.java
1 /**
2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
5 *
6 * The contents of this file are subject to the Mozilla Public License Version 1.1
7 * See LICENSE.TXT at the top of this package for the full license terms.
8 */
9
10 package eu.etaxonomy.cdm.persistence.dao.hibernate.common;
11
12 import java.util.ArrayList;
13 import java.util.List;
14 import java.util.UUID;
15
16 import org.apache.log4j.Logger;
17 import org.apache.lucene.analysis.standard.StandardAnalyzer;
18 import org.apache.lucene.queryparser.classic.ParseException;
19 import org.apache.lucene.queryparser.classic.QueryParser;
20 import org.hibernate.Criteria;
21 import org.hibernate.Query;
22 import org.hibernate.Session;
23 import org.hibernate.criterion.Criterion;
24 import org.hibernate.criterion.Order;
25 import org.hibernate.criterion.Projections;
26 import org.hibernate.criterion.Restrictions;
27 import org.hibernate.envers.query.AuditEntity;
28 import org.hibernate.envers.query.AuditQuery;
29 import org.hibernate.search.FullTextSession;
30 import org.hibernate.search.Search;
31 import org.hibernate.search.SearchFactory;
32
33 import eu.etaxonomy.cdm.model.common.CdmBase;
34 import eu.etaxonomy.cdm.model.common.Credit;
35 import eu.etaxonomy.cdm.model.common.DefinedTerm;
36 import eu.etaxonomy.cdm.model.common.IdentifiableEntity;
37 import eu.etaxonomy.cdm.model.common.IdentifiableSource;
38 import eu.etaxonomy.cdm.model.common.LSID;
39 import eu.etaxonomy.cdm.model.common.MarkerType;
40 import eu.etaxonomy.cdm.model.media.Rights;
41 import eu.etaxonomy.cdm.persistence.dao.QueryParseException;
42 import eu.etaxonomy.cdm.persistence.dao.common.IIdentifiableDao;
43 import eu.etaxonomy.cdm.persistence.query.MatchMode;
44 import eu.etaxonomy.cdm.persistence.query.OrderHint;
45
46
47 public class IdentifiableDaoBase<T extends IdentifiableEntity>
48 extends AnnotatableDaoImpl<T>
49 implements IIdentifiableDao<T>{
50
51 @SuppressWarnings("unused")
52 private static final Logger logger = Logger.getLogger(IdentifiableDaoBase.class);
53
54 protected String defaultField = "titleCache_tokenized";
55 protected Class<? extends T> indexedClasses[];
56
57
58
59 public IdentifiableDaoBase(Class<T> type) {
60 super(type);
61 }
62
63
64 @Override
65 public List<T> findByTitle(String queryString) {
66 return findByTitle(queryString, null);
67 }
68
69 @Override
70 public List<T> findByTitle(String queryString, CdmBase sessionObject) {
71 /**
72 * FIXME why do we need to call update in a find* method? I don't know for sure
73 * that this is a good idea . . .
74 */
75 Session session = getSession();
76 if ( sessionObject != null ) {
77 session.update(sessionObject);
78 }
79 checkNotInPriorView("IdentifiableDaoBase.findByTitle(String queryString, CdmBase sessionObject)");
80 Criteria crit = session.createCriteria(type);
81 crit.add(Restrictions.ilike("titleCache", queryString));
82 List<T> results = crit.list();
83 List<String> propertyPaths = null;
84 defaultBeanInitializer.initializeAll(results, propertyPaths);
85 return results;
86 }
87
88 @Override
89 public List<T> findByTitleAndClass(String queryString, Class<T> clazz) {
90 checkNotInPriorView("IdentifiableDaoBase.findByTitleAndClass(String queryString, Class<T> clazz)");
91 Criteria crit = getSession().createCriteria(clazz);
92 crit.add(Restrictions.ilike("titleCache", queryString));
93 List<T> results = crit.list();
94 return results;
95 }
96
97 @Override
98 public List<T> findTitleCache(Class<? extends T> clazz, String queryString, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, MatchMode matchMode){
99
100 Query query = prepareFindTitleCache(clazz, queryString, pageSize,
101 pageNumber, matchMode, false);
102 List<T> result = query.list();
103 return result;
104 }
105
106 @Override
107 public Long countTitleCache(Class<? extends T> clazz, String queryString, MatchMode matchMode){
108
109 Query query = prepareFindTitleCache(clazz, queryString, null,
110 null, matchMode, true);
111 Long result = (Long)query.uniqueResult();
112 return result;
113 }
114
115 /**
116 * @param clazz filter by class - can be null to include all instances of type T
117 * @param queryString the query string to filter by
118 * @param pageSize
119 * @param pageNumber
120 * @param matchmode use a particular type of matching (can be null - defaults to exact matching)
121 * @return
122 */
123 private Query prepareFindTitleCache(Class<? extends T> clazz,
124 String queryString, Integer pageSize, Integer pageNumber,
125 MatchMode matchMode, boolean doCount) {
126 if(clazz == null) {
127 clazz = type;
128 }
129
130 String what = (doCount ? "count(distinct e.titleCache)": "distinct e.titleCache");
131
132 if(matchMode != null){
133 queryString = matchMode.queryStringFrom(queryString);
134 }
135 String hql = "select " + what + " from " + clazz.getName() + " e where e.titleCache like '" + queryString + "'";
136
137 Query query = getSession().createQuery(hql);
138
139 if(pageSize != null && !doCount) {
140 query.setMaxResults(pageSize);
141 if(pageNumber != null) {
142 query.setFirstResult(pageNumber * pageSize);
143 }
144 }
145 return query;
146 }
147
148
149 @Override
150 public List<T> findByTitle(Class<? extends T> clazz, String queryString, MatchMode matchmode, List<Criterion> criterion, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
151 return findByParam(clazz, "titleCache", queryString, matchmode, criterion, pageSize, pageNumber, orderHints, propertyPaths);
152 }
153
154 @Override
155 public List<T> findByReferenceTitle(Class<? extends T> clazz, String queryString, MatchMode matchmode, List<Criterion> criterion, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths) {
156 return findByParam(clazz, "title", queryString, matchmode, criterion, pageSize, pageNumber, orderHints, propertyPaths);
157 }
158
159 @Override
160 public List<T> findByTitle(String queryString, MatchMode matchmode, int page, int pagesize, List<Criterion> criteria) {
161 checkNotInPriorView("IdentifiableDaoBase.findByTitle(String queryString, MATCH_MODE matchmode, int page, int pagesize, List<Criterion> criteria)");
162 Criteria crit = getSession().createCriteria(type);
163 if (matchmode == MatchMode.EXACT) {
164 crit.add(Restrictions.eq("titleCache", matchmode.queryStringFrom(queryString)));
165 } else {
166 // crit.add(Restrictions.ilike("titleCache", matchmode.queryStringFrom(queryString)));
167 crit.add(Restrictions.like("titleCache", matchmode.queryStringFrom(queryString)));
168 }
169 if (pagesize >= 0) {
170 crit.setMaxResults(pagesize);
171 }
172 if(criteria != null){
173 for (Criterion criterion : criteria) {
174 crit.add(criterion);
175 }
176 }
177 crit.addOrder(Order.asc("titleCache"));
178 int firstItem = (page - 1) * pagesize;
179 crit.setFirstResult(firstItem);
180 List<T> results = crit.list();
181 List<String> propertyPaths = null;
182 defaultBeanInitializer.initializeAll(results, propertyPaths);
183 return results;
184 }
185
186 @Override
187 public int countRights(T identifiableEntity) {
188 checkNotInPriorView("IdentifiableDaoBase.countRights(T identifiableEntity)");
189 Query query = getSession().createQuery("select count(rights) from " + type.getSimpleName() + " identifiableEntity join identifiableEntity.rights rights where identifiableEntity = :identifiableEntity");
190 query.setParameter("identifiableEntity",identifiableEntity);
191 return ((Long)query.uniqueResult()).intValue();
192 }
193
194 @Override
195 public int countSources(T identifiableEntity) {
196 checkNotInPriorView("IdentifiableDaoBase.countSources(T identifiableEntity)");
197 Query query = getSession().createQuery("SELECT COUNT(source) FROM "+identifiableEntity.getClass().getName() + " ie JOIN ie.sources source WHERE ie = :identifiableEntity");
198 query.setParameter("identifiableEntity", identifiableEntity);
199 return ((Long)query.uniqueResult()).intValue();
200 }
201
202 @Override
203 public List<Rights> getRights(T identifiableEntity, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
204 checkNotInPriorView("IdentifiableDaoBase.getRights(T identifiableEntity, Integer pageSize, Integer pageNumber, List<String> propertyPaths)");
205 Query query = getSession().createQuery("select rights from " + type.getSimpleName() + " identifiableEntity join identifiableEntity.rights rights where identifiableEntity = :identifiableEntity");
206 query.setParameter("identifiableEntity",identifiableEntity);
207 setPagingParameter(query, pageSize, pageNumber);
208 List<Rights> results = query.list();
209 defaultBeanInitializer.initializeAll(results, propertyPaths);
210 return results;
211 }
212
213 // @Override //TODO add to interface, maybe add property path
214 public List<Credit> getCredits(T identifiableEntity, Integer pageSize, Integer pageNumber) {
215 checkNotInPriorView("IdentifiableDaoBase.getCredits(T identifiableEntity, Integer pageSize, Integer pageNumber)");
216 Query query = getSession().createQuery("select credits from " + type.getSimpleName() + " identifiableEntity join identifiableEntity.credits credits where identifiableEntity = :identifiableEntity");
217 query.setParameter("identifiableEntity",identifiableEntity);
218 setPagingParameter(query, pageSize, pageNumber);
219 return query.list();
220 }
221
222 @Override
223 public List<IdentifiableSource> getSources(T identifiableEntity, Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
224 checkNotInPriorView("IdentifiableDaoBase.getSources(T identifiableEntity, Integer pageSize, Integer pageNumber)");
225 Query query = getSession().createQuery("SELECT source FROM "+ identifiableEntity.getClass().getName()+ " ie JOIN ie.sources source WHERE ie.id = :id");
226 query.setParameter("id",identifiableEntity.getId());
227 setPagingParameter(query, pageSize, pageNumber);
228 @SuppressWarnings("unchecked")
229 List<IdentifiableSource> results = query.list();
230 defaultBeanInitializer.initializeAll(results, propertyPaths);
231 return results;
232 }
233
234 @Override
235 public List<T> findOriginalSourceByIdInSource(String idInSource, String idNamespace) {
236 checkNotInPriorView("IdentifiableDaoBase.findOriginalSourceByIdInSource(String idInSource, String idNamespace)");
237 Query query = getSession().createQuery(
238 "Select c from " + type.getSimpleName() + " as c " +
239 "inner join c.sources as source " +
240 "where source.idInSource = :idInSource " +
241 " AND source.idNamespace = :idNamespace"
242 );
243 query.setString("idInSource", idInSource);
244 query.setString("idNamespace", idNamespace);
245 //TODO integrate reference in where
246 return query.list();
247 }
248
249 @Override
250 public T find(LSID lsid) {
251 checkNotInPriorView("IdentifiableDaoBase.find(LSID lsid)");
252 Criteria criteria = getSession().createCriteria(type);
253 criteria.add(Restrictions.eq("lsid.authority", lsid.getAuthority()));
254 criteria.add(Restrictions.eq("lsid.namespace", lsid.getNamespace()));
255 criteria.add(Restrictions.eq("lsid.object", lsid.getObject()));
256
257 if(lsid.getRevision() != null) {
258 criteria.add(Restrictions.eq("lsid.revision", lsid.getRevision()));
259 }
260
261 T object = (T)criteria.uniqueResult();
262 if(object != null) {
263 return object;
264 } else {
265 AuditQuery query = getAuditReader().createQuery().forRevisionsOfEntity(type, false, true);
266 query.add(AuditEntity.property("lsid_authority").eq(lsid.getAuthority()));
267 query.add(AuditEntity.property("lsid_namespace").eq(lsid.getNamespace()));
268 query.add(AuditEntity.property("lsid_object").eq(lsid.getObject()));
269
270 if(lsid.getRevision() != null) {
271 query.add(AuditEntity.property("lsid_revision").eq(lsid.getRevision()));
272 }
273
274 query.addOrder(AuditEntity.revisionNumber().asc());
275 query.setMaxResults(1);
276 query.setFirstResult(0);
277 List<Object[]> objs = query.getResultList();
278 if(objs.isEmpty()) {
279 return null;
280 } else {
281 return (T)objs.get(0)[0];
282 }
283 }
284 }
285
286
287
288 @SuppressWarnings("deprecation")
289 @Override
290 public String getTitleCache(UUID uuid, boolean refresh){
291 if (! refresh){
292 String queryStr = String.format("SELECT titleCache FROM %s t WHERE t.uuid = '%s'", type.getSimpleName() , uuid.toString());
293 Query query = getSession().createQuery(queryStr);
294 List<?> list = query.list();
295 return list.isEmpty()? null : (String)list.get(0);
296 }else{
297 T entity = this.findByUuid(uuid);
298 if (entity == null){
299 return null;
300 }
301 entity.setTitleCache(null);
302 return entity.getTitleCache();
303 }
304 }
305
306
307
308 @Override
309 public long countByTitle(Class<? extends T> clazz, String queryString, MatchMode matchmode, List<Criterion> criterion) {
310 return countByParam(clazz, "titleCache",queryString,matchmode,criterion);
311 }
312
313 @Override
314 public long countByReferenceTitle(Class<? extends T> clazz, String queryString, MatchMode matchmode, List<Criterion> criterion) {
315 return countByParam(clazz, "title",queryString,matchmode,criterion);
316 }
317
318 @Override
319 public int count(Class<? extends T> clazz, String queryString) {
320 checkNotInPriorView("IdentifiableDaoBase.count(Class<? extends T> clazz, String queryString)");
321 QueryParser queryParser = new QueryParser(defaultField , new StandardAnalyzer());
322
323 try {
324 org.apache.lucene.search.Query query = queryParser.parse(queryString);
325
326 FullTextSession fullTextSession = Search.getFullTextSession(this.getSession());
327 org.hibernate.search.FullTextQuery fullTextQuery = null;
328
329 if(clazz == null) {
330 fullTextQuery = fullTextSession.createFullTextQuery(query, type);
331 } else {
332 fullTextQuery = fullTextSession.createFullTextQuery(query, clazz);
333 }
334
335 Integer result = fullTextQuery.getResultSize();
336 return result;
337
338 } catch (ParseException e) {
339 throw new QueryParseException(e, queryString);
340 }
341 }
342
343 @Override
344 public void optimizeIndex() {
345 FullTextSession fullTextSession = Search.getFullTextSession(getSession());
346 SearchFactory searchFactory = fullTextSession.getSearchFactory();
347 for(Class clazz : indexedClasses) {
348 searchFactory.optimize(clazz); // optimize the indices ()
349 }
350 fullTextSession.flushToIndexes();
351 }
352
353 @Override
354 public void purgeIndex() {
355 FullTextSession fullTextSession = Search.getFullTextSession(getSession());
356 for(Class clazz : indexedClasses) {
357 fullTextSession.purgeAll(clazz); // remove all objects of type t from indexes
358 }
359 fullTextSession.flushToIndexes();
360 }
361
362 @Override
363 public void rebuildIndex() {
364 FullTextSession fullTextSession = Search.getFullTextSession(getSession());
365
366 for(T t : list(null,null)) { // re-index all objects
367 fullTextSession.index(t);
368 }
369 fullTextSession.flushToIndexes();
370 }
371
372 @Override
373 public List<T> search(Class<? extends T> clazz, String queryString, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints,List<String> propertyPaths) {
374 checkNotInPriorView("IdentifiableDaoBase.search(Class<? extends T> clazz, String queryString, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints,List<String> propertyPaths)");
375 QueryParser queryParser = new QueryParser(defaultField, new StandardAnalyzer());
376 List<T> results = new ArrayList<T>();
377
378 try {
379 org.apache.lucene.search.Query query = queryParser.parse(queryString);
380
381 FullTextSession fullTextSession = Search.getFullTextSession(getSession());
382 org.hibernate.search.FullTextQuery fullTextQuery = null;
383
384 if(clazz == null) {
385 fullTextQuery = fullTextSession.createFullTextQuery(query, type);
386 } else {
387 fullTextQuery = fullTextSession.createFullTextQuery(query, clazz);
388 }
389
390 addOrder(fullTextQuery,orderHints);
391
392 if(pageSize != null) {
393 fullTextQuery.setMaxResults(pageSize);
394 if(pageNumber != null) {
395 fullTextQuery.setFirstResult(pageNumber * pageSize);
396 } else {
397 fullTextQuery.setFirstResult(0);
398 }
399 }
400
401 List<T> result = fullTextQuery.list();
402 defaultBeanInitializer.initializeAll(result, propertyPaths);
403 return result;
404
405 } catch (ParseException e) {
406 throw new QueryParseException(e, queryString);
407 }
408 }
409
410 @Override
411 public String suggestQuery(String string) {
412 throw new UnsupportedOperationException("suggestQuery is not supported for objects of class " + type.getName());
413 }
414
415 @Override
416 public Integer countByTitle(String queryString) {
417 return countByTitle(queryString, null);
418 }
419
420 @Override
421 public Integer countByTitle(String queryString, CdmBase sessionObject) {
422 Session session = getSession();
423 if ( sessionObject != null ) {
424 session.update(sessionObject);
425 }
426 checkNotInPriorView("IdentifiableDaoBase.countByTitle(String queryString, CdmBase sessionObject)");
427 Criteria crit = session.createCriteria(type);
428 crit.add(Restrictions.ilike("titleCache", queryString));
429 Integer result = ((Number)crit.setProjection(Projections.rowCount()).uniqueResult()).intValue();
430 return result;
431 }
432
433 @Override
434 public Integer countByTitle(String queryString, MatchMode matchMode, List<Criterion> criteria) {
435 checkNotInPriorView("IdentifiableDaoBase.findByTitle(String queryString, MATCH_MODE matchmode, int page, int pagesize, List<Criterion> criteria)");
436 Criteria crit = getSession().createCriteria(type);
437 if (matchMode == MatchMode.EXACT) {
438 crit.add(Restrictions.eq("titleCache", matchMode.queryStringFrom(queryString)));
439 } else {
440 // crit.add(Restrictions.ilike("titleCache", matchmode.queryStringFrom(queryString)));
441 crit.add(Restrictions.like("titleCache", matchMode.queryStringFrom(queryString)));
442 }
443
444 if(criteria != null){
445 for (Criterion criterion : criteria) {
446 crit.add(criterion);
447 }
448 }
449
450
451 Integer result = ((Number)crit.setProjection(Projections.rowCount()).uniqueResult()).intValue();
452 return result;
453 }
454
455
456 @Override
457 public <S extends T> int countByIdentifier(Class<S> clazz,
458 String identifier, DefinedTerm identifierType, MatchMode matchmode) {
459 checkNotInPriorView("IdentifiableDaoBase.countByIdentifier(T clazz, String identifier, DefinedTerm identifierType, MatchMode matchmode)");
460
461 Class<?> clazzParam = clazz == null ? type : clazz;
462 String queryString = "SELECT count(*) FROM " + clazzParam.getSimpleName() + " as c " +
463 "INNER JOIN c.identifiers as ids " +
464 "WHERE (1=1) ";
465 if (identifier != null){
466 if (matchmode == null || matchmode == MatchMode.EXACT){
467 queryString += " AND ids.identifier = '" + identifier + "'";
468 }else {
469 queryString += " AND ids.identifier LIKE '" + matchmode.queryStringFrom(identifier) + "'";
470 }
471 }
472 if (identifierType != null){
473 queryString += " AND ids.type = :type";
474 }
475
476 Query query = getSession().createQuery(queryString);
477 if (identifierType != null){
478 query.setEntity("type", identifierType);
479 }
480
481 Long c = (Long)query.uniqueResult();
482 return c.intValue();
483 }
484
485 @Override
486 public <S extends T> List<Object[]> findByIdentifier(
487 Class<S> clazz, String identifier, DefinedTerm identifierType,
488 MatchMode matchmode, boolean includeEntity,
489 Integer pageSize, Integer pageNumber, List<String> propertyPaths) {
490
491 checkNotInPriorView("IdentifiableDaoBase.findByIdentifier(T clazz, String identifier, DefinedTerm identifierType, MatchMode matchmode, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths)");
492
493 Class<?> clazzParam = clazz == null ? type : clazz;
494 String queryString = "SELECT ids.type, ids.identifier, %s FROM %s as c " +
495 " INNER JOIN c.identifiers as ids " +
496 " WHERE (1=1) ";
497 queryString = String.format(queryString, (includeEntity ? "c":"c.uuid, c.titleCache") , clazzParam.getSimpleName());
498
499 //Matchmode and identifier
500 if (identifier != null){
501 if (matchmode == null || matchmode == MatchMode.EXACT){
502 queryString += " AND ids.identifier = '" + identifier + "'";
503 }else {
504 queryString += " AND ids.identifier LIKE '" + matchmode.queryStringFrom(identifier) + "'";
505 }
506 }
507 if (identifierType != null){
508 queryString += " AND ids.type = :type";
509 }
510 //order
511 queryString +=" ORDER BY ids.type.uuid, ids.identifier, c.uuid ";
512
513 Query query = getSession().createQuery(queryString);
514
515 //parameters
516 if (identifierType != null){
517 query.setEntity("type", identifierType);
518 }
519
520 //paging
521 setPagingParameter(query, pageSize, pageNumber);
522
523 List<Object[]> results = query.list();
524 //initialize
525 if (includeEntity){
526 List<S> entities = new ArrayList<S>();
527 for (Object[] result : results){
528 entities.add((S)result[2]);
529 }
530 defaultBeanInitializer.initializeAll(entities, propertyPaths);
531 }
532 return results;
533 }
534
535 @Override
536 public <S extends T> long countByMarker(Class<S> clazz, MarkerType markerType,
537 Boolean markerValue) {
538 checkNotInPriorView("IdentifiableDaoBase.countByMarker(T clazz, MarkerType markerType, Boolean markerValue)");
539
540 if (markerType == null){
541 return 0;
542 }
543 Class<?> clazzParam = clazz == null ? type : clazz;
544 String queryString = "SELECT count(*) FROM " + clazzParam.getSimpleName() + " as c " +
545 "INNER JOIN c.markers as mks " +
546 "WHERE (1=1) ";
547
548 if (markerValue != null){
549 queryString += " AND mks.flag = :flag";
550 }
551 queryString += " AND mks.markerType = :type";
552
553 Query query = getSession().createQuery(queryString);
554 query.setEntity("type", markerType);
555 if (markerValue != null){
556 query.setBoolean("flag", markerValue);
557 }
558
559 Long c = (Long)query.uniqueResult();
560 return c;
561 }
562
563 @Override
564 public <S extends T> List<Object[]> findByMarker(
565 Class<S> clazz, MarkerType markerType,
566 Boolean markerValue, boolean includeEntity, Integer pageSize, Integer pageNumber,
567 List<String> propertyPaths) {
568
569 checkNotInPriorView("IdentifiableDaoBase.findByMarker(T clazz, String identifier, DefinedTerm identifierType, MatchMode matchmode, Integer pageSize, Integer pageNumber, List<OrderHint> orderHints, List<String> propertyPaths)");
570 if (markerType == null){
571 return new ArrayList<Object[]>();
572 }
573
574 Class<?> clazzParam = clazz == null ? type : clazz;
575 String queryString = "SELECT mks.markerType, mks.flag, %s FROM %s as c " +
576 " INNER JOIN c.markers as mks " +
577 " WHERE (1=1) ";
578 queryString = String.format(queryString, (includeEntity ? "c":"c.uuid, c.titleCache") , clazzParam.getSimpleName());
579
580 //Matchmode and identifier
581 if (markerValue != null){
582 queryString += " AND mks.flag = :flag";
583 }
584 queryString += " AND mks.markerType = :type";
585
586 //order
587 queryString +=" ORDER BY mks.markerType.uuid, mks.flag, c.uuid ";
588
589 Query query = getSession().createQuery(queryString);
590
591 //parameters
592 query.setEntity("type", markerType);
593 if (markerValue != null){
594 query.setBoolean("flag", markerValue);
595 }
596
597 //paging
598 setPagingParameter(query, pageSize, pageNumber);
599
600 @SuppressWarnings("unchecked")
601 List<Object[]> results = query.list();
602 //initialize
603 if (includeEntity){
604 List<S> entities = new ArrayList<S>();
605 for (Object[] result : results){
606 entities.add((S)result[2]);
607 }
608 defaultBeanInitializer.initializeAll(entities, propertyPaths);
609 }
610 return results;
611 }
612
613 }