2 * Copyright (C) 2007 EDIT
3 * European Distributed Institute of Taxonomy
4 * http://www.e-taxonomy.eu
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.
10 package eu
.etaxonomy
.cdm
.persistence
.dao
.hibernate
.common
;
12 import java
.lang
.reflect
.Field
;
13 import java
.util
.ArrayList
;
14 import java
.util
.Collection
;
15 import java
.util
.HashMap
;
16 import java
.util
.HashSet
;
17 import java
.util
.Iterator
;
18 import java
.util
.List
;
21 import java
.util
.UUID
;
23 import org
.apache
.log4j
.Logger
;
24 import org
.apache
.lucene
.search
.Sort
;
25 import org
.apache
.lucene
.search
.SortField
;
26 import org
.hibernate
.Criteria
;
27 import org
.hibernate
.FlushMode
;
28 import org
.hibernate
.HibernateException
;
29 import org
.hibernate
.LockOptions
;
30 import org
.hibernate
.NonUniqueObjectException
;
31 import org
.hibernate
.Query
;
32 import org
.hibernate
.Session
;
33 import org
.hibernate
.criterion
.Criterion
;
34 import org
.hibernate
.criterion
.DetachedCriteria
;
35 import org
.hibernate
.criterion
.Example
;
36 import org
.hibernate
.criterion
.Example
.PropertySelector
;
37 import org
.hibernate
.criterion
.Order
;
38 import org
.hibernate
.criterion
.ProjectionList
;
39 import org
.hibernate
.criterion
.Projections
;
40 import org
.hibernate
.criterion
.Restrictions
;
41 import org
.hibernate
.envers
.query
.AuditQuery
;
42 import org
.hibernate
.metadata
.ClassMetadata
;
43 import org
.hibernate
.search
.FullTextQuery
;
44 import org
.hibernate
.type
.Type
;
45 import org
.joda
.time
.DateTime
;
46 import org
.springframework
.beans
.factory
.annotation
.Autowired
;
47 import org
.springframework
.dao
.DataAccessException
;
48 import org
.springframework
.dao
.InvalidDataAccessApiUsageException
;
49 import org
.springframework
.security
.core
.Authentication
;
50 import org
.springframework
.security
.core
.context
.SecurityContextHolder
;
51 import org
.springframework
.stereotype
.Repository
;
52 import org
.springframework
.util
.ReflectionUtils
;
54 import eu
.etaxonomy
.cdm
.model
.common
.CdmBase
;
55 import eu
.etaxonomy
.cdm
.model
.common
.User
;
56 import eu
.etaxonomy
.cdm
.model
.common
.VersionableEntity
;
57 import eu
.etaxonomy
.cdm
.persistence
.dao
.common
.ICdmEntityDao
;
58 import eu
.etaxonomy
.cdm
.persistence
.dao
.initializer
.IBeanInitializer
;
59 import eu
.etaxonomy
.cdm
.persistence
.dto
.MergeResult
;
60 import eu
.etaxonomy
.cdm
.persistence
.hibernate
.PostMergeEntityListener
;
61 import eu
.etaxonomy
.cdm
.persistence
.hibernate
.replace
.ReferringObjectMetadata
;
62 import eu
.etaxonomy
.cdm
.persistence
.hibernate
.replace
.ReferringObjectMetadataFactory
;
63 import eu
.etaxonomy
.cdm
.persistence
.query
.Grouping
;
64 import eu
.etaxonomy
.cdm
.persistence
.query
.MatchMode
;
65 import eu
.etaxonomy
.cdm
.persistence
.query
.OrderHint
;
70 * FIXME CdmEntityDaoBase is abstract, can it be annotated with @Repository?
73 public abstract class CdmEntityDaoBase
<T
extends CdmBase
> extends DaoBase
implements ICdmEntityDao
<T
> {
74 private static final Logger logger
= Logger
.getLogger(CdmEntityDaoBase
.class);
76 protected int flushAfterNo
= 1000; //large numbers may cause synchronisation errors when commiting the session !!
78 protected Class
<T
> type
;
80 // protected Version version = Configuration.luceneVersion;
83 // @Qualifier("defaultBeanInitializer")
84 protected IBeanInitializer defaultBeanInitializer
;
86 public void setDefaultBeanInitializer(IBeanInitializer defaultBeanInitializer
) {
87 this.defaultBeanInitializer
= defaultBeanInitializer
;
91 private ReferringObjectMetadataFactory referringObjectMetadataFactory
;
94 public CdmEntityDaoBase(Class
<T
> type
){
96 logger
.debug("Creating DAO of type [" + type
.getSimpleName() + "]");
100 public void lock(T t
, LockOptions lockOptions
) {
101 getSession().buildLockRequest(lockOptions
).lock(t
);
105 public void refresh(T t
, LockOptions lockOptions
, List
<String
> propertyPaths
) {
106 getSession().refresh(t
, lockOptions
);
107 defaultBeanInitializer
.initialize(t
, propertyPaths
);
110 //TODO this method should be moved to a concrete class (not typed)
111 public UUID
saveCdmObj(CdmBase cdmObj
) throws DataAccessException
{
112 getSession().saveOrUpdate(cdmObj
);
113 return cdmObj
.getUuid();
116 //TODO: Replace saveCdmObj() by saveCdmObject_
117 private UUID
saveCdmObject_(T cdmObj
){
118 getSession().saveOrUpdate(cdmObj
);
119 return cdmObj
.getUuid();
122 //TODO: Use everywhere CdmEntityDaoBase.saveAll() instead of ServiceBase.saveCdmObjectAll()?
123 //TODO: why does this use saveCdmObject_ which actually savesOrUpdateds data ?
125 public Map
<UUID
, T
> saveAll(Collection
<T
> cdmObjCollection
){
126 int types
= cdmObjCollection
.getClass().getTypeParameters().length
;
128 if (logger
.isDebugEnabled()){logger
.debug("ClassType: + " + cdmObjCollection
.getClass().getTypeParameters()[0]);}
131 Map
<UUID
, T
> resultMap
= new HashMap
<UUID
, T
>();
132 Iterator
<T
> iterator
= cdmObjCollection
.iterator();
134 while(iterator
.hasNext()){
135 if ( ( (i
% 2000) == 0) && (i
> 0) ){logger
.debug("Saved " + i
+ " objects" );}
136 T cdmObj
= iterator
.next();
137 UUID uuid
= saveCdmObject_(cdmObj
);
138 if (logger
.isDebugEnabled()){logger
.debug("Save cdmObj: " + (cdmObj
== null?
null: cdmObj
.toString()));}
139 resultMap
.put(uuid
, cdmObj
);
141 if ( (i
% flushAfterNo
) == 0){
143 if (logger
.isDebugEnabled()){logger
.debug("flush");}
146 logger
.error("An exception occurred when trying to flush data");
148 throw new RuntimeException(e
);
153 if ( logger
.isInfoEnabled() ){logger
.info("Saved " + i
+ " objects" );}
157 private UUID
saveOrUpdateCdmObject(T cdmObj
){
158 getSession().saveOrUpdate(cdmObj
);
159 return cdmObj
.getUuid();
163 public Map
<UUID
, T
> saveOrUpdateAll(Collection
<T
> cdmObjCollection
){
164 int types
= cdmObjCollection
.getClass().getTypeParameters().length
;
166 if (logger
.isDebugEnabled()){logger
.debug("ClassType: + " + cdmObjCollection
.getClass().getTypeParameters()[0]);}
169 Map
<UUID
, T
> resultMap
= new HashMap
<UUID
, T
>();
170 Iterator
<T
> iterator
= cdmObjCollection
.iterator();
172 while(iterator
.hasNext()){
173 if ( ( (i
% 2000) == 0) && (i
> 0) ){logger
.debug("Saved " + i
+ " objects" );}
174 T cdmObj
= iterator
.next();
175 UUID uuid
= saveOrUpdateCdmObject(cdmObj
);
176 if (logger
.isDebugEnabled()){logger
.debug("Save cdmObj: " + (cdmObj
== null?
null: cdmObj
.toString()));}
177 resultMap
.put(uuid
, cdmObj
);
179 if ( (i
% flushAfterNo
) == 0){
181 if (logger
.isDebugEnabled()){logger
.debug("flush");}
184 logger
.error("An exception occurred when trying to flush data");
186 throw new RuntimeException(e
);
191 if ( logger
.isInfoEnabled() ){logger
.info("Saved " + i
+ " objects" );}
199 public T
replace(T x
, T y
) {
204 Class
<?
> commonClass
= x
.getClass();
206 while(!commonClass
.isAssignableFrom(y
.getClass())) {
207 if(commonClass
.equals(type
)) {
208 throw new RuntimeException();
210 commonClass
= commonClass
.getSuperclass();
214 getSession().merge(x
);
216 Set
<ReferringObjectMetadata
> referringObjectMetas
= referringObjectMetadataFactory
.get(x
.getClass());
218 for(ReferringObjectMetadata referringObjectMetadata
: referringObjectMetas
) {
220 List
<CdmBase
> referringObjects
= referringObjectMetadata
.getReferringObjects(x
, getSession());
222 for(CdmBase referringObject
: referringObjects
) {
224 referringObjectMetadata
.replace(referringObject
,x
,y
);
225 getSession().update(referringObject
);
227 } catch (IllegalArgumentException e
) {
228 throw new RuntimeException(e
.getMessage(),e
);
229 } catch (IllegalAccessException e
) {
230 throw new RuntimeException(e
.getMessage(),e
);
238 public Session
getSession() throws DataAccessException
{
239 return super.getSession();
243 public void clear() throws DataAccessException
{
244 Session session
= getSession();
246 if (logger
.isDebugEnabled()){logger
.debug("dao clear end");}
250 public MergeResult
<T
> merge(T transientObject
, boolean returnTransientEntity
) throws DataAccessException
{
251 Session session
= getSession();
252 PostMergeEntityListener
.addSession(session
);
253 MergeResult
<T
> result
= null;
255 @SuppressWarnings("unchecked")
256 T persistentObject
= (T
)session
.merge(transientObject
);
257 if (logger
.isDebugEnabled()){logger
.debug("dao merge end");}
259 if(returnTransientEntity
) {
260 if(transientObject
!= null && persistentObject
!= null) {
261 transientObject
.setId(persistentObject
.getId());
263 result
= new MergeResult(transientObject
, PostMergeEntityListener
.getNewEntities(session
));
265 result
= new MergeResult(persistentObject
, null);
269 PostMergeEntityListener
.removeSession(session
);
274 public T
merge(T transientObject
) throws DataAccessException
{
275 Session session
= getSession();
276 @SuppressWarnings("unchecked")
277 T persistentObject
= (T
)session
.merge(transientObject
);
278 if (logger
.isDebugEnabled()){logger
.debug("dao merge end");}
279 return persistentObject
;
283 public UUID
saveOrUpdate(T transientObject
) throws DataAccessException
{
284 if (transientObject
== null){
285 logger
.warn("Object to save should not be null. NOP");
289 if (logger
.isDebugEnabled()){logger
.debug("dao saveOrUpdate start...");}
290 if (logger
.isDebugEnabled()){logger
.debug("transientObject(" + transientObject
.getClass().getSimpleName() + ") ID:" + transientObject
.getId() + ", UUID: " + transientObject
.getUuid()) ;}
291 Session session
= getSession();
292 if(transientObject
.getId() != 0 && VersionableEntity
.class.isAssignableFrom(transientObject
.getClass())) {
293 VersionableEntity versionableEntity
= (VersionableEntity
)transientObject
;
294 versionableEntity
.setUpdated(new DateTime());
295 Authentication authentication
= SecurityContextHolder
.getContext().getAuthentication();
296 if(authentication
!= null && authentication
.getPrincipal() != null && authentication
.getPrincipal() instanceof User
) {
297 User user
= (User
)authentication
.getPrincipal();
298 versionableEntity
.setUpdatedBy(user
);
301 session
.saveOrUpdate(transientObject
);
302 if (logger
.isDebugEnabled()){logger
.debug("dao saveOrUpdate end");}
303 return transientObject
.getUuid();
304 } catch (NonUniqueObjectException e
) {
305 logger
.error("Error in CdmEntityDaoBase.saveOrUpdate(obj)");
306 logger
.error(e
.getIdentifier());
307 logger
.error(e
.getEntityName());
308 logger
.error(e
.getMessage());
312 } catch (HibernateException e
) {
320 public T
save(T newInstance
) throws DataAccessException
{
321 if (newInstance
== null){
322 logger
.warn("Object to save should not be null. NOP");
325 getSession().save(newInstance
);
330 public UUID
update(T transientObject
) throws DataAccessException
{
331 if (transientObject
== null){
332 logger
.warn("Object to update should not be null. NOP");
335 getSession().update(transientObject
);
336 return transientObject
.getUuid();
340 public UUID
refresh(T persistentObject
) throws DataAccessException
{
341 getSession().refresh(persistentObject
);
342 return persistentObject
.getUuid();
346 public UUID
delete(T persistentObject
) throws DataAccessException
{
347 if (persistentObject
== null){
348 logger
.warn(type
.getName() + " was 'null'");
352 // Merge the object in if it is detached
354 // I think this is preferable to catching lazy initialization errors
355 // as that solution only swallows and hides the exception, but doesn't
356 // actually solve it.
357 persistentObject
= (T
) getSession().merge(persistentObject
);
358 getSession().delete(persistentObject
);
359 return persistentObject
.getUuid();
363 public T
findById(int id
) throws DataAccessException
{
364 return getSession().get(type
, id
);
369 public T
findByUuid(UUID uuid
) throws DataAccessException
{
370 Session session
= getSession();
371 Criteria crit
= session
.createCriteria(type
);
372 crit
.add(Restrictions
.eq("uuid", uuid
));
373 crit
.addOrder(Order
.desc("created"));
374 @SuppressWarnings("unchecked")
375 List
<T
> results
= crit
.list();
376 Set
<T
> resultSet
= new HashSet
<>();
377 resultSet
.addAll(results
);
378 if (resultSet
.isEmpty()){
381 if(resultSet
.size() > 1){
382 logger
.error("findByUuid() delivers more than one result for UUID: " + uuid
);
384 return results
.get(0);
389 public T
findByUuidWithoutFlush(UUID uuid
) throws DataAccessException
{
390 Session session
= getSession();
391 FlushMode currentFlushMode
= session
.getFlushMode();
393 // set flush mode to manual so that the session does not flush
394 // when before performing the query
395 session
.setFlushMode(FlushMode
.MANUAL
);
396 Criteria crit
= session
.createCriteria(type
);
397 crit
.add(Restrictions
.eq("uuid", uuid
));
398 crit
.addOrder(Order
.desc("created"));
399 @SuppressWarnings("unchecked")
400 List
<T
> results
= crit
.list();
401 if (results
.isEmpty()){
404 if(results
.size() > 1){
405 logger
.error("findByUuid() delivers more than one result for UUID: " + uuid
);
407 return results
.get(0);
410 // set back the session flush mode
411 if(currentFlushMode
!= null) {
412 session
.setFlushMode(currentFlushMode
);
418 public List
<T
> loadList(Collection
<Integer
> ids
, List
<String
> propertyPaths
) throws DataAccessException
{
421 return new ArrayList
<T
>(0);
424 Criteria criteria
= prepareList(ids
, null, null, null, "id");
426 if (logger
.isDebugEnabled()){logger
.debug(criteria
.toString());}
428 @SuppressWarnings("unchecked")
429 List
<T
> result
= criteria
.list();
430 defaultBeanInitializer
.initializeAll(result
, propertyPaths
);
436 public List
<T
> list(Collection
<UUID
> uuids
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) throws DataAccessException
{
438 Criteria criteria
= prepareList(uuids
, pageSize
, pageNumber
, orderHints
, "uuid");
440 @SuppressWarnings("unchecked")
441 List
<T
> result
= criteria
.list();
442 defaultBeanInitializer
.initializeAll(result
, propertyPaths
);
451 * @param propertyName
454 private Criteria
prepareList(Collection
<?
> uuids
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, String propertyName
) {
455 Criteria criteria
= getSession().createCriteria(type
);
456 criteria
.add(Restrictions
.in(propertyName
, uuids
));
458 if(pageSize
!= null) {
459 criteria
.setMaxResults(pageSize
);
460 if(pageNumber
!= null) {
461 criteria
.setFirstResult(pageNumber
* pageSize
);
463 criteria
.setFirstResult(0);
467 if(orderHints
== null) {
468 orderHints
= OrderHint
.defaultOrderHintsFor(type
);
470 addOrder(criteria
, orderHints
);
475 protected List
<T
> findByParam(Class
<?
extends T
> clazz
, String param
, String queryString
, MatchMode matchmode
, List
<Criterion
> criterion
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
476 Criteria criteria
= null;
479 criteria
= getSession().createCriteria(type
);
481 criteria
= getSession().createCriteria(clazz
);
484 if (queryString
!= null) {
485 if(matchmode
== null) {
486 criteria
.add(Restrictions
.ilike(param
, queryString
));
487 } else if(matchmode
== MatchMode
.BEGINNING
) {
488 criteria
.add(Restrictions
.ilike(param
, queryString
, org
.hibernate
.criterion
.MatchMode
.START
));
489 } else if(matchmode
== MatchMode
.END
) {
490 criteria
.add(Restrictions
.ilike(param
, queryString
, org
.hibernate
.criterion
.MatchMode
.END
));
491 } else if(matchmode
== MatchMode
.EXACT
) {
492 criteria
.add(Restrictions
.ilike(param
, queryString
, org
.hibernate
.criterion
.MatchMode
.EXACT
));
494 criteria
.add(Restrictions
.ilike(param
, queryString
, org
.hibernate
.criterion
.MatchMode
.ANYWHERE
));
498 addCriteria(criteria
, criterion
);
500 if(pageSize
!= null) {
501 criteria
.setMaxResults(pageSize
);
502 if(pageNumber
!= null) {
503 criteria
.setFirstResult(pageNumber
* pageSize
);
505 criteria
.setFirstResult(0);
509 addOrder(criteria
, orderHints
);
511 @SuppressWarnings("unchecked")
512 List
<T
> result
= criteria
.list();
513 defaultBeanInitializer
.initializeAll(result
, propertyPaths
);
518 public T
load(UUID uuid
) {
519 T bean
= findByUuid(uuid
);
523 defaultBeanInitializer
.load(bean
);
529 public T
load(int id
, List
<String
> propertyPaths
){
530 T bean
= findById(id
);
534 defaultBeanInitializer
.initialize(bean
, propertyPaths
);
540 public T
load(UUID uuid
, List
<String
> propertyPaths
){
541 T bean
= findByUuid(uuid
);
545 defaultBeanInitializer
.initialize(bean
, propertyPaths
);
551 public Boolean
exists(UUID uuid
) {
552 if (findByUuid(uuid
)==null){
564 public int count(Class
<?
extends T
> clazz
) {
565 Session session
= getSession();
566 Criteria criteria
= null;
568 criteria
= session
.createCriteria(type
);
570 criteria
= session
.createCriteria(clazz
);
572 criteria
.setProjection(Projections
.projectionList().add(Projections
.rowCount()));
574 //since hibernate 4 (or so) uniqueResult returns Long, not Integer, therefore needs
575 //to be casted. Think about returning long rather then int!
576 return ((Number
) criteria
.uniqueResult()).intValue();
580 public List
<T
> list(Integer limit
, Integer start
) {
581 return list(limit
, start
, null);
585 public List
<Object
[]> group(Class
<?
extends T
> clazz
,Integer limit
, Integer start
, List
<Grouping
> groups
, List
<String
> propertyPaths
) {
587 Criteria criteria
= null;
589 criteria
= getSession().createCriteria(type
);
591 criteria
= getSession().createCriteria(clazz
);
594 addGroups(criteria
,groups
);
597 criteria
.setFirstResult(start
);
598 criteria
.setMaxResults(limit
);
601 @SuppressWarnings("unchecked")
602 List
<Object
[]> result
= criteria
.list();
604 if(propertyPaths
!= null && !propertyPaths
.isEmpty()) {
605 for(Object
[] objects
: result
) {
606 defaultBeanInitializer
.initialize(objects
[0], propertyPaths
);
613 protected void countGroups(DetachedCriteria criteria
,List
<Grouping
> groups
) {
617 Map
<String
,String
> aliases
= new HashMap
<String
,String
>();
619 for(Grouping grouping
: groups
) {
620 if(grouping
.getAssociatedObj() != null) {
622 if((alias
= aliases
.get(grouping
.getAssociatedObj())) == null) {
623 alias
= grouping
.getAssociatedObjectAlias();
624 aliases
.put(grouping
.getAssociatedObj(), alias
);
625 criteria
.createAlias(grouping
.getAssociatedObj(),alias
);
630 ProjectionList projectionList
= Projections
.projectionList();
632 for(Grouping grouping
: groups
) {
633 grouping
.addProjection(projectionList
);
635 criteria
.setProjection(projectionList
);
639 protected void addGroups(Criteria criteria
,List
<Grouping
> groups
) {
643 Map
<String
,String
> aliases
= new HashMap
<String
,String
>();
645 for(Grouping grouping
: groups
) {
646 if(grouping
.getAssociatedObj() != null) {
648 if((alias
= aliases
.get(grouping
.getAssociatedObj())) == null) {
649 alias
= grouping
.getAssociatedObjectAlias();
650 aliases
.put(grouping
.getAssociatedObj(), alias
);
651 criteria
.createAlias(grouping
.getAssociatedObj(),alias
);
656 ProjectionList projectionList
= Projections
.projectionList();
658 for(Grouping grouping
: groups
) {
659 grouping
.addProjection(projectionList
);
661 criteria
.setProjection(projectionList
);
663 for(Grouping grouping
: groups
) {
664 grouping
.addOrder(criteria
);
670 protected void addCriteria(Criteria criteria
, List
<Criterion
> criterion
) {
671 if(criterion
!= null) {
672 for(Criterion c
: criterion
) {
679 protected void addOrder(FullTextQuery fullTextQuery
, List
<OrderHint
> orderHints
) {
680 //FIXME preliminary hardcoded type:
681 SortField
.Type type
= SortField
.Type
.STRING
;
683 if(orderHints
!= null && !orderHints
.isEmpty()) {
684 org
.apache
.lucene
.search
.Sort sort
= new Sort();
685 SortField
[] sortFields
= new SortField
[orderHints
.size()];
686 for(int i
= 0; i
< orderHints
.size(); i
++) {
687 OrderHint orderHint
= orderHints
.get(i
);
688 switch(orderHint
.getSortOrder()) {
690 sortFields
[i
] = new SortField(orderHint
.getPropertyName(), type
, true);
694 sortFields
[i
] = new SortField(orderHint
.getPropertyName(), type
, false);
698 sort
.setSort(sortFields
);
699 fullTextQuery
.setSort(sort
);
705 public List
<T
> list(Integer limit
, Integer start
, List
<OrderHint
> orderHints
) {
706 return list(limit
,start
,orderHints
,null);
710 public List
<T
> list(Integer limit
, Integer start
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
711 Criteria criteria
= getSession().createCriteria(type
);
713 criteria
.setFirstResult(start
);
714 criteria
.setMaxResults(limit
);
717 addOrder(criteria
,orderHints
);
718 @SuppressWarnings("unchecked")
719 List
<T
> results
= criteria
.list();
721 defaultBeanInitializer
.initializeAll(results
, propertyPaths
);
726 public <S
extends T
> List
<S
> list(Class
<S
> clazz
, Integer limit
, Integer start
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
727 Criteria criteria
= null;
729 criteria
= getSession().createCriteria(type
);
731 criteria
= getSession().createCriteria(clazz
);
736 criteria
.setFirstResult(start
);
738 criteria
.setFirstResult(0);
740 criteria
.setMaxResults(limit
);
743 addOrder(criteria
,orderHints
);
745 @SuppressWarnings("unchecked")
746 List
<S
> results
= criteria
.list();
748 defaultBeanInitializer
.initializeAll(results
, propertyPaths
);
753 public <S
extends T
> List
<S
> list(Class
<S
> type
, Integer limit
, Integer start
, List
<OrderHint
> orderHints
) {
754 return list(type
,limit
,start
,orderHints
,null);
758 public <S
extends T
> List
<S
> list(Class
<S
> type
, Integer limit
, Integer start
) {
759 return list(type
,limit
,start
,null,null);
763 public List
<T
> rows(String tableName
, int limit
, int start
) {
764 Query query
= getSession().createQuery("from " + tableName
+ " order by uuid");
765 query
.setFirstResult(start
);
766 query
.setMaxResults(limit
);
767 @SuppressWarnings("unchecked")
768 List
<T
> result
= query
.list();
773 public Class
<T
> getType() {
777 protected void setPagingParameter(Query query
, Integer pageSize
, Integer pageNumber
){
778 if(pageSize
!= null) {
779 query
.setMaxResults(pageSize
);
780 if(pageNumber
!= null) {
781 query
.setFirstResult(pageNumber
* pageSize
);
783 query
.setFirstResult(0);
788 protected void setPagingParameter(AuditQuery query
, Integer pageSize
, Integer pageNumber
){
789 if(pageSize
!= null) {
790 query
.setMaxResults(pageSize
);
791 if(pageNumber
!= null) {
792 query
.setFirstResult(pageNumber
* pageSize
);
794 query
.setFirstResult(0);
800 public int count(T example
, Set
<String
> includeProperties
) {
801 Criteria criteria
= getSession().createCriteria(example
.getClass());
802 addExample(criteria
,example
,includeProperties
);
804 criteria
.setProjection(Projections
.rowCount());
805 return ((Number
)criteria
.uniqueResult()).intValue();
808 protected void addExample(Criteria criteria
, T example
, Set
<String
> includeProperties
) {
809 if(includeProperties
!= null && !includeProperties
.isEmpty()) {
810 criteria
.add(Example
.create(example
).setPropertySelector(new PropertySelectorImpl(includeProperties
)));
811 ClassMetadata classMetadata
= getSession().getSessionFactory().getClassMetadata(example
.getClass());
812 for(String property
: includeProperties
) {
813 Type type
= classMetadata
.getPropertyType(property
);
814 if(type
.isEntityType()) {
816 Field field
= ReflectionUtils
.findField(example
.getClass(), property
);
817 field
.setAccessible(true);
818 Object value
= field
.get(example
);
820 criteria
.add(Restrictions
.eq(property
,value
));
822 criteria
.add(Restrictions
.isNull(property
));
824 } catch (SecurityException se
) {
825 throw new InvalidDataAccessApiUsageException("Tried to add criteria for property " + property
, se
);
826 } catch (HibernateException he
) {
827 throw new InvalidDataAccessApiUsageException("Tried to add criteria for property " + property
, he
);
828 } catch (IllegalArgumentException iae
) {
829 throw new InvalidDataAccessApiUsageException("Tried to add criteria for property " + property
, iae
);
830 } catch (IllegalAccessException ie
) {
831 throw new InvalidDataAccessApiUsageException("Tried to add criteria for property " + property
, ie
);
837 criteria
.add(Example
.create(example
));
842 protected int countByParam(Class
<?
extends T
> clazz
, String param
, String queryString
, MatchMode matchmode
, List
<Criterion
> criterion
) {
843 Criteria criteria
= null;
846 criteria
= getSession().createCriteria(type
);
848 criteria
= getSession().createCriteria(clazz
);
851 if (queryString
!= null) {
852 if(matchmode
== null) {
853 criteria
.add(Restrictions
.ilike(param
, queryString
));
854 } else if(matchmode
== MatchMode
.BEGINNING
) {
855 criteria
.add(Restrictions
.ilike(param
, queryString
, org
.hibernate
.criterion
.MatchMode
.START
));
856 } else if(matchmode
== MatchMode
.END
) {
857 criteria
.add(Restrictions
.ilike(param
, queryString
, org
.hibernate
.criterion
.MatchMode
.END
));
858 } else if(matchmode
== MatchMode
.EXACT
) {
859 criteria
.add(Restrictions
.ilike(param
, queryString
, org
.hibernate
.criterion
.MatchMode
.EXACT
));
861 criteria
.add(Restrictions
.ilike(param
, queryString
, org
.hibernate
.criterion
.MatchMode
.ANYWHERE
));
865 addCriteria(criteria
, criterion
);
867 criteria
.setProjection(Projections
.rowCount());
869 // List<T> result = criteria.list();
870 return ((Number
)criteria
.uniqueResult()).intValue();
875 public List
<T
> list(T example
, Set
<String
> includeProperties
, Integer limit
, Integer start
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
876 Criteria criteria
= getSession().createCriteria(example
.getClass());
877 addExample(criteria
,example
,includeProperties
);
881 criteria
.setFirstResult(start
);
883 criteria
.setFirstResult(0);
885 criteria
.setMaxResults(limit
);
888 addOrder(criteria
,orderHints
);
890 @SuppressWarnings("unchecked")
891 List
<T
> results
= criteria
.list();
892 defaultBeanInitializer
.initializeAll(results
, propertyPaths
);
896 private class PropertySelectorImpl
implements PropertySelector
{
898 private final Set
<String
> includeProperties
;
902 private static final long serialVersionUID
= -3175311800911570546L;
904 public PropertySelectorImpl(Set
<String
> includeProperties
) {
905 this.includeProperties
= includeProperties
;
909 public boolean include(Object propertyValue
, String propertyName
, Type type
) {
910 if(includeProperties
.contains(propertyName
)) {