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
<>();
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 if (uuids
== null || uuids
.isEmpty()){
439 return new ArrayList
<>();
442 Criteria criteria
= prepareList(uuids
, pageSize
, pageNumber
, orderHints
, "uuid");
444 @SuppressWarnings("unchecked")
445 List
<T
> result
= criteria
.list();
446 defaultBeanInitializer
.initializeAll(result
, propertyPaths
);
455 * @param propertyName
458 private Criteria
prepareList(Collection
<?
> uuids
, Integer pageSize
, Integer pageNumber
, List
<OrderHint
> orderHints
, String propertyName
) {
459 Criteria criteria
= getSession().createCriteria(type
);
460 criteria
.add(Restrictions
.in(propertyName
, uuids
));
462 if(pageSize
!= null) {
463 criteria
.setMaxResults(pageSize
);
464 if(pageNumber
!= null) {
465 criteria
.setFirstResult(pageNumber
* pageSize
);
467 criteria
.setFirstResult(0);
471 if(orderHints
== null) {
472 orderHints
= OrderHint
.defaultOrderHintsFor(type
);
474 addOrder(criteria
, orderHints
);
479 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
) {
480 Criteria criteria
= null;
483 criteria
= getSession().createCriteria(type
);
485 criteria
= getSession().createCriteria(clazz
);
488 if (queryString
!= null) {
489 if(matchmode
== null) {
490 criteria
.add(Restrictions
.ilike(param
, queryString
));
491 } else if(matchmode
== MatchMode
.BEGINNING
) {
492 criteria
.add(Restrictions
.ilike(param
, queryString
, org
.hibernate
.criterion
.MatchMode
.START
));
493 } else if(matchmode
== MatchMode
.END
) {
494 criteria
.add(Restrictions
.ilike(param
, queryString
, org
.hibernate
.criterion
.MatchMode
.END
));
495 } else if(matchmode
== MatchMode
.EXACT
) {
496 criteria
.add(Restrictions
.ilike(param
, queryString
, org
.hibernate
.criterion
.MatchMode
.EXACT
));
498 criteria
.add(Restrictions
.ilike(param
, queryString
, org
.hibernate
.criterion
.MatchMode
.ANYWHERE
));
502 addCriteria(criteria
, criterion
);
504 if(pageSize
!= null) {
505 criteria
.setMaxResults(pageSize
);
506 if(pageNumber
!= null) {
507 criteria
.setFirstResult(pageNumber
* pageSize
);
509 criteria
.setFirstResult(0);
513 addOrder(criteria
, orderHints
);
515 @SuppressWarnings("unchecked")
516 List
<T
> result
= criteria
.list();
517 defaultBeanInitializer
.initializeAll(result
, propertyPaths
);
522 public T
load(UUID uuid
) {
523 T bean
= findByUuid(uuid
);
527 defaultBeanInitializer
.load(bean
);
533 public T
load(int id
, List
<String
> propertyPaths
){
534 T bean
= findById(id
);
538 defaultBeanInitializer
.initialize(bean
, propertyPaths
);
544 public T
load(UUID uuid
, List
<String
> propertyPaths
){
545 T bean
= findByUuid(uuid
);
549 defaultBeanInitializer
.initialize(bean
, propertyPaths
);
555 public Boolean
exists(UUID uuid
) {
556 if (findByUuid(uuid
)==null){
568 public int count(Class
<?
extends T
> clazz
) {
569 Session session
= getSession();
570 Criteria criteria
= null;
572 criteria
= session
.createCriteria(type
);
574 criteria
= session
.createCriteria(clazz
);
576 criteria
.setProjection(Projections
.projectionList().add(Projections
.rowCount()));
578 //since hibernate 4 (or so) uniqueResult returns Long, not Integer, therefore needs
579 //to be casted. Think about returning long rather then int!
580 return ((Number
) criteria
.uniqueResult()).intValue();
584 public List
<T
> list(Integer limit
, Integer start
) {
585 return list(limit
, start
, null);
589 public List
<Object
[]> group(Class
<?
extends T
> clazz
,Integer limit
, Integer start
, List
<Grouping
> groups
, List
<String
> propertyPaths
) {
591 Criteria criteria
= null;
593 criteria
= getSession().createCriteria(type
);
595 criteria
= getSession().createCriteria(clazz
);
598 addGroups(criteria
,groups
);
601 criteria
.setFirstResult(start
);
602 criteria
.setMaxResults(limit
);
605 @SuppressWarnings("unchecked")
606 List
<Object
[]> result
= criteria
.list();
608 if(propertyPaths
!= null && !propertyPaths
.isEmpty()) {
609 for(Object
[] objects
: result
) {
610 defaultBeanInitializer
.initialize(objects
[0], propertyPaths
);
617 protected void countGroups(DetachedCriteria criteria
,List
<Grouping
> groups
) {
621 Map
<String
,String
> aliases
= new HashMap
<String
,String
>();
623 for(Grouping grouping
: groups
) {
624 if(grouping
.getAssociatedObj() != null) {
626 if((alias
= aliases
.get(grouping
.getAssociatedObj())) == null) {
627 alias
= grouping
.getAssociatedObjectAlias();
628 aliases
.put(grouping
.getAssociatedObj(), alias
);
629 criteria
.createAlias(grouping
.getAssociatedObj(),alias
);
634 ProjectionList projectionList
= Projections
.projectionList();
636 for(Grouping grouping
: groups
) {
637 grouping
.addProjection(projectionList
);
639 criteria
.setProjection(projectionList
);
643 protected void addGroups(Criteria criteria
,List
<Grouping
> groups
) {
647 Map
<String
,String
> aliases
= new HashMap
<String
,String
>();
649 for(Grouping grouping
: groups
) {
650 if(grouping
.getAssociatedObj() != null) {
652 if((alias
= aliases
.get(grouping
.getAssociatedObj())) == null) {
653 alias
= grouping
.getAssociatedObjectAlias();
654 aliases
.put(grouping
.getAssociatedObj(), alias
);
655 criteria
.createAlias(grouping
.getAssociatedObj(),alias
);
660 ProjectionList projectionList
= Projections
.projectionList();
662 for(Grouping grouping
: groups
) {
663 grouping
.addProjection(projectionList
);
665 criteria
.setProjection(projectionList
);
667 for(Grouping grouping
: groups
) {
668 grouping
.addOrder(criteria
);
674 protected void addCriteria(Criteria criteria
, List
<Criterion
> criterion
) {
675 if(criterion
!= null) {
676 for(Criterion c
: criterion
) {
683 protected void addOrder(FullTextQuery fullTextQuery
, List
<OrderHint
> orderHints
) {
684 //FIXME preliminary hardcoded type:
685 SortField
.Type type
= SortField
.Type
.STRING
;
687 if(orderHints
!= null && !orderHints
.isEmpty()) {
688 org
.apache
.lucene
.search
.Sort sort
= new Sort();
689 SortField
[] sortFields
= new SortField
[orderHints
.size()];
690 for(int i
= 0; i
< orderHints
.size(); i
++) {
691 OrderHint orderHint
= orderHints
.get(i
);
692 switch(orderHint
.getSortOrder()) {
694 sortFields
[i
] = new SortField(orderHint
.getPropertyName(), type
, true);
698 sortFields
[i
] = new SortField(orderHint
.getPropertyName(), type
, false);
702 sort
.setSort(sortFields
);
703 fullTextQuery
.setSort(sort
);
709 public List
<T
> list(Integer limit
, Integer start
, List
<OrderHint
> orderHints
) {
710 return list(limit
,start
,orderHints
,null);
714 public List
<T
> list(Integer limit
, Integer start
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
715 Criteria criteria
= getSession().createCriteria(type
);
717 criteria
.setFirstResult(start
);
718 criteria
.setMaxResults(limit
);
721 addOrder(criteria
,orderHints
);
722 @SuppressWarnings("unchecked")
723 List
<T
> results
= criteria
.list();
725 defaultBeanInitializer
.initializeAll(results
, propertyPaths
);
730 public <S
extends T
> List
<S
> list(Class
<S
> clazz
, Integer limit
, Integer start
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
731 Criteria criteria
= null;
733 criteria
= getSession().createCriteria(type
);
735 criteria
= getSession().createCriteria(clazz
);
740 criteria
.setFirstResult(start
);
742 criteria
.setFirstResult(0);
744 criteria
.setMaxResults(limit
);
747 addOrder(criteria
, orderHints
);
749 @SuppressWarnings("unchecked")
750 List
<S
> results
= criteria
.list();
752 defaultBeanInitializer
.initializeAll(results
, propertyPaths
);
757 public <S
extends T
> List
<S
> list(Class
<S
> type
, Integer limit
, Integer start
, List
<OrderHint
> orderHints
) {
758 return list(type
,limit
,start
,orderHints
,null);
762 public <S
extends T
> List
<S
> list(Class
<S
> type
, Integer limit
, Integer start
) {
763 return list(type
,limit
,start
,null,null);
767 public List
<T
> rows(String tableName
, int limit
, int start
) {
768 Query query
= getSession().createQuery("from " + tableName
+ " order by uuid");
769 query
.setFirstResult(start
);
770 query
.setMaxResults(limit
);
771 @SuppressWarnings("unchecked")
772 List
<T
> result
= query
.list();
777 public Class
<T
> getType() {
781 protected void setPagingParameter(Query query
, Integer pageSize
, Integer pageNumber
){
782 if(pageSize
!= null) {
783 query
.setMaxResults(pageSize
);
784 if(pageNumber
!= null) {
785 query
.setFirstResult(pageNumber
* pageSize
);
787 query
.setFirstResult(0);
792 protected void setPagingParameter(AuditQuery query
, Integer pageSize
, Integer pageNumber
){
793 if(pageSize
!= null) {
794 query
.setMaxResults(pageSize
);
795 if(pageNumber
!= null) {
796 query
.setFirstResult(pageNumber
* pageSize
);
798 query
.setFirstResult(0);
804 public int count(T example
, Set
<String
> includeProperties
) {
805 Criteria criteria
= getSession().createCriteria(example
.getClass());
806 addExample(criteria
,example
,includeProperties
);
808 criteria
.setProjection(Projections
.rowCount());
809 return ((Number
)criteria
.uniqueResult()).intValue();
812 protected void addExample(Criteria criteria
, T example
, Set
<String
> includeProperties
) {
813 if(includeProperties
!= null && !includeProperties
.isEmpty()) {
814 criteria
.add(Example
.create(example
).setPropertySelector(new PropertySelectorImpl(includeProperties
)));
815 ClassMetadata classMetadata
= getSession().getSessionFactory().getClassMetadata(example
.getClass());
816 for(String property
: includeProperties
) {
817 Type type
= classMetadata
.getPropertyType(property
);
818 if(type
.isEntityType()) {
820 Field field
= ReflectionUtils
.findField(example
.getClass(), property
);
821 field
.setAccessible(true);
822 Object value
= field
.get(example
);
824 criteria
.add(Restrictions
.eq(property
,value
));
826 criteria
.add(Restrictions
.isNull(property
));
828 } catch (SecurityException se
) {
829 throw new InvalidDataAccessApiUsageException("Tried to add criteria for property " + property
, se
);
830 } catch (HibernateException he
) {
831 throw new InvalidDataAccessApiUsageException("Tried to add criteria for property " + property
, he
);
832 } catch (IllegalArgumentException iae
) {
833 throw new InvalidDataAccessApiUsageException("Tried to add criteria for property " + property
, iae
);
834 } catch (IllegalAccessException ie
) {
835 throw new InvalidDataAccessApiUsageException("Tried to add criteria for property " + property
, ie
);
841 criteria
.add(Example
.create(example
));
846 protected long countByParam(Class
<?
extends T
> clazz
, String param
, String queryString
, MatchMode matchmode
, List
<Criterion
> criterion
) {
847 Criteria criteria
= null;
850 criteria
= getSession().createCriteria(type
);
852 criteria
= getSession().createCriteria(clazz
);
855 if (queryString
!= null) {
856 if(matchmode
== null) {
857 criteria
.add(Restrictions
.ilike(param
, queryString
));
858 } else if(matchmode
== MatchMode
.BEGINNING
) {
859 criteria
.add(Restrictions
.ilike(param
, queryString
, org
.hibernate
.criterion
.MatchMode
.START
));
860 } else if(matchmode
== MatchMode
.END
) {
861 criteria
.add(Restrictions
.ilike(param
, queryString
, org
.hibernate
.criterion
.MatchMode
.END
));
862 } else if(matchmode
== MatchMode
.EXACT
) {
863 criteria
.add(Restrictions
.ilike(param
, queryString
, org
.hibernate
.criterion
.MatchMode
.EXACT
));
865 criteria
.add(Restrictions
.ilike(param
, queryString
, org
.hibernate
.criterion
.MatchMode
.ANYWHERE
));
869 addCriteria(criteria
, criterion
);
871 criteria
.setProjection(Projections
.rowCount());
873 return ((Number
)criteria
.uniqueResult()).longValue();
878 public List
<T
> list(T example
, Set
<String
> includeProperties
, Integer limit
, Integer start
, List
<OrderHint
> orderHints
, List
<String
> propertyPaths
) {
879 Criteria criteria
= getSession().createCriteria(example
.getClass());
880 addExample(criteria
,example
,includeProperties
);
884 criteria
.setFirstResult(start
);
886 criteria
.setFirstResult(0);
888 criteria
.setMaxResults(limit
);
891 addOrder(criteria
,orderHints
);
893 @SuppressWarnings("unchecked")
894 List
<T
> results
= criteria
.list();
895 defaultBeanInitializer
.initializeAll(results
, propertyPaths
);
899 private class PropertySelectorImpl
implements PropertySelector
{
901 private final Set
<String
> includeProperties
;
905 private static final long serialVersionUID
= -3175311800911570546L;
907 public PropertySelectorImpl(Set
<String
> includeProperties
) {
908 this.includeProperties
= includeProperties
;
912 public boolean include(Object propertyValue
, String propertyName
, Type type
) {
913 if(includeProperties
.contains(propertyName
)) {