1 package net.sf.r4h;
2
3 import static net.sf.r4h.Restrictions.equal;
4
5 import java.beans.Introspector;
6 import java.beans.PropertyDescriptor;
7 import java.io.Serializable;
8 import java.sql.Types;
9 import java.util.ArrayList;
10 import java.util.Arrays;
11 import java.util.Collection;
12 import java.util.Collections;
13 import java.util.HashMap;
14 import java.util.HashSet;
15 import java.util.List;
16 import java.util.Map;
17 import java.util.Set;
18
19 import net.sf.r4h.Restrictions.CaseAwareRestriction;
20 import net.sf.r4h.Restrictions.EmptinessAwareRestriction;
21 import net.sf.r4h.Restrictions.ExampleRestriction;
22
23 import org.hibernate.Criteria;
24 import org.hibernate.HibernateException;
25 import org.hibernate.PropertyAccessException;
26 import org.hibernate.Query;
27 import org.hibernate.Session;
28 import org.hibernate.SessionFactory;
29 import org.hibernate.criterion.Conjunction;
30 import org.hibernate.criterion.CriteriaQuery;
31 import org.hibernate.criterion.Criterion;
32 import org.hibernate.criterion.Example;
33 import org.hibernate.criterion.LikeExpression;
34 import org.hibernate.criterion.Projections;
35 import org.hibernate.criterion.SimpleExpression;
36 import org.hibernate.engine.spi.SessionFactoryImplementor;
37 import org.hibernate.internal.SessionFactoryImpl;
38 import org.hibernate.persister.entity.EntityPersister;
39 import org.hibernate.sql.JoinType;
40 import org.hibernate.tuple.NonIdentifierAttribute;
41 import org.hibernate.tuple.StandardProperty;
42 import org.hibernate.type.CollectionType;
43 import org.hibernate.type.ManyToOneType;
44 import org.hibernate.type.Type;
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65 public class HibernateRepository<E, I extends Serializable> {
66
67 private static final Partition ALL_IN_ONE_PARTITION = new Partition(0, Integer.MAX_VALUE);
68 private final SessionFactory sessionFactory;
69 private final Class<E> entityClass;
70
71
72
73
74
75
76
77
78 public HibernateRepository(SessionFactory sessionFactory, Class<E> entityClass) {
79 if (sessionFactory != null && !(sessionFactory instanceof SessionFactoryImpl)) {
80 throw new IllegalArgumentException("SessionFactory is not instance of " + SessionFactoryImpl.class.getCanonicalName());
81 }
82 this.sessionFactory = sessionFactory;
83 this.entityClass = entityClass;
84 }
85
86 public List<E> list(ExampleRestriction restriction, E exampleObject, Page page, Order... orderStrategies) {
87 return list("", restriction, exampleObject, pageToPartition(page), orderStrategies);
88 }
89
90 public List<E> list(ExampleRestriction restriction, E exampleObject, Partition partition, Order... orderStrategies) {
91 return list("", restriction, exampleObject, partition, orderStrategies);
92 }
93
94 public List<E> list(E exampleObject, Page page, Order... orderStrategies) {
95 return list(Restrictions.example(), exampleObject, pageToPartition(page), orderStrategies);
96 }
97
98 public List<E> list(E exampleObject, Partition partition, Order... orderStrategies) {
99 return list(Restrictions.example(), exampleObject, partition, orderStrategies);
100 }
101
102 @SuppressWarnings("unchecked")
103 public List<E> list(ExampleRestriction restriction, Object exampleObject, Order... orderStrategies) {
104 return list(restriction, (E) exampleObject, ALL_IN_ONE_PARTITION, orderStrategies);
105 }
106
107 public List<E> list(E exampleObject, Order... orderStrategies) {
108 return list(Restrictions.example(), exampleObject, orderStrategies);
109 }
110
111 public Long count(ExampleRestriction restriction, E exampleObject) {
112 return count("", restriction, exampleObject);
113 }
114
115 public Long count(E exampleObject) {
116 return count(Restrictions.example(), exampleObject);
117 }
118
119 public List<E> list(String[] properties, Restrictions.Restriction[] restrictions, Object[] values, Page page, Order... orderStrategies) {
120 return execute(new CriteriaHibernateCallback<E>(entityClass, properties, restrictions, values, pageToPartition(page), getSessionFactoryImplementor()).addOrder(orderStrategies));
121 }
122
123 public List<E> list(String[] properties, Restrictions.Restriction[] restrictions, Object[] values, Partition partition, Order... orderStrategies) {
124 return execute(new CriteriaHibernateCallback<E>(entityClass, properties, restrictions, values, partition, getSessionFactoryImplementor()).addOrder(orderStrategies));
125 }
126
127 public List<E> list(String[] properties, Restrictions.Restriction[] restrictions, Object[] values, Order... orderStrategies) {
128 return list(properties, restrictions, values, ALL_IN_ONE_PARTITION, orderStrategies);
129 }
130
131 public Long count(String[] properties, Restrictions.Restriction[] restrictions, Object[] values) {
132 return execute(new CriteriaHibernateCallback<E>(entityClass, properties, restrictions, values, getSessionFactoryImplementor()).setReturnCount());
133 }
134
135 public List<E> list(String property, Restrictions.Restriction restriction, Object value, Page page, Order... orderStrategies) {
136 return list(new String[] { property }, new Restrictions.Restriction[] { restriction }, new Object[] { value }, pageToPartition(page), orderStrategies);
137 }
138
139 public List<E> list(String property, Restrictions.Restriction restriction, Object value, Partition partition, Order... orderStrategies) {
140 return list(new String[] { property }, new Restrictions.Restriction[] { restriction }, new Object[] { value }, partition, orderStrategies);
141 }
142
143 public List<E> list(String property, Restrictions.Restriction restriction, Object value, Order... orderStrategies) {
144 return list(new String[] { property }, new Restrictions.Restriction[] { restriction }, new Object[] { value }, orderStrategies);
145 }
146
147 public Long count(String property, Restrictions.Restriction restriction, Object value) {
148 return count(new String[] { property }, new Restrictions.Restriction[] { restriction }, new Object[] { value });
149 }
150
151 public List<E> list(String property, Object value, Page page, Order... orderStrategies) {
152 return list(property, equal(), value, pageToPartition(page), orderStrategies);
153 }
154
155 public List<E> list(String property, Object value, Partition partition, Order... orderStrategies) {
156 return list(property, equal(), value, partition, orderStrategies);
157 }
158
159 public List<E> list(String property, Object value, Order... orderStrategies) {
160 return list(property, value, ALL_IN_ONE_PARTITION, orderStrategies);
161 }
162
163 public Long count(String property, Object value) {
164 return count(property, equal(), value);
165 }
166
167 public List<E> list(String[] properties, Object[] values, Page page, Order... orderStrategies) {
168 return list(properties, HibernateRepository.createArrayOfEqualRestrictions(properties.length), values, pageToPartition(page), orderStrategies);
169 }
170
171 public List<E> list(String[] properties, Object[] values, Partition partition, Order... orderStrategies) {
172 return list(properties, HibernateRepository.createArrayOfEqualRestrictions(properties.length), values, partition, orderStrategies);
173 }
174
175 public List<E> list(String[] properties, Object[] values, Order... orderStrategies) {
176 return list(properties, HibernateRepository.createArrayOfEqualRestrictions(properties.length), values, orderStrategies);
177 }
178
179 public Long count(String[] properties, Object[] values) {
180 return count(properties, HibernateRepository.createArrayOfEqualRestrictions(properties.length), values);
181 }
182
183 public List<E> list(Page page, Order... orderStrategies) {
184 return list(HibernateRepositoryUtils.properties(), HibernateRepositoryUtils.values(), pageToPartition(page), orderStrategies);
185 }
186
187 public List<E> list(Partition partition, Order... orderStrategies) {
188 return list(HibernateRepositoryUtils.properties(), HibernateRepositoryUtils.values(), partition, orderStrategies);
189 }
190
191 public List<E> list(Order... orderStrategies) {
192 return list(ALL_IN_ONE_PARTITION, orderStrategies);
193 }
194
195
196
197
198 public Long count() {
199 return execute(new CriteriaHibernateCallback<E>(entityClass).setReturnCount());
200 }
201
202 @SuppressWarnings("unchecked")
203 public E get(I id) {
204 return (E) sessionFactory.getCurrentSession().get(entityClass, id);
205 }
206
207 public boolean contains(E entity) {
208 return sessionFactory.getCurrentSession().contains(entity);
209 }
210
211 @SuppressWarnings("unchecked")
212 public <T> List<T> listByHql(String hql, String[] namedParams, Object[] values) {
213 Query createQuery = sessionFactory.getCurrentSession().createQuery(hql);
214 for (int i = 0; i < values.length; i++) {
215 createQuery.setParameter(namedParams[i], values[i]);
216 }
217 return createQuery.list();
218 }
219
220 @SuppressWarnings("unchecked")
221 public <T> List<T> listByHql(String hql) {
222 return sessionFactory.getCurrentSession().createQuery(hql).list();
223 }
224
225 @SuppressWarnings("unchecked")
226 public <T> List<T> listByHql(String hql, Object... values) {
227 Query createQuery = sessionFactory.getCurrentSession().createQuery(hql);
228 for (int i = 0; i < values.length; i++) {
229 createQuery.setParameter(i, values[i]);
230 }
231 return createQuery.list();
232 }
233
234 @SuppressWarnings("unchecked")
235 public E unique(String[] properties, Restrictions.Restriction[] restrictions, Object[] values) {
236
237 return (E) execute(new CriteriaHibernateCallback<E>(entityClass, properties, restrictions, values, getSessionFactoryImplementor()).setUnique());
238 }
239
240 public E unique(String[] properties, Object[] values) {
241 return unique(properties, HibernateRepository.createArrayOfEqualRestrictions(properties.length), values);
242 }
243
244 public E unique(String propertyName, Restrictions.Restriction restrictions, Object propertyValue) {
245 return unique(new String[] { propertyName }, HibernateRepositoryUtils.restrictions(restrictions), new Object[] { propertyValue });
246 }
247
248 public E unique(String propertyName, Object propertyValue) {
249 return unique(propertyName, equal(), propertyValue);
250 }
251
252 public Session getCurrentSession() {
253 return sessionFactory.getCurrentSession();
254 }
255
256 @SuppressWarnings("unchecked")
257 public E load(I id) {
258 return (E) getCurrentSession().load(entityClass, id);
259 }
260
261 @SuppressWarnings("unchecked")
262 public List<E> loadAll() {
263 return getCurrentSession().createCriteria(entityClass).list();
264 }
265
266 public E saveOrUpdate(E entity) {
267 getCurrentSession().saveOrUpdate(entity);
268 return entity;
269 }
270
271
272
273
274
275
276
277 public E saveOrUpdateAndFlush(E entity) {
278 entity = saveOrUpdate(entity);
279 getCurrentSession().flush();
280 return entity;
281 }
282
283 public E save(E entity) {
284 getCurrentSession().save(entity);
285 return entity;
286 }
287
288
289
290
291
292
293
294 public E saveAndFlush(E entity) {
295 entity = save(entity);
296 getCurrentSession().flush();
297 return entity;
298 }
299
300 public E merge(E entity) {
301 getCurrentSession().merge(entity);
302 return entity;
303 }
304
305 public E delete(E entity) {
306 getCurrentSession().delete(entity);
307 return entity;
308 }
309
310 public E delete(Serializable id) {
311 @SuppressWarnings("unchecked")
312 E entity = (E) getCurrentSession().load(entityClass, id);
313 getCurrentSession().delete(entity);
314 return entity;
315 }
316
317
318
319
320
321
322
323 public int deleteAll(String entityName) {
324 return getCurrentSession().createQuery("delete from " + entityName).executeUpdate();
325 }
326
327
328
329
330
331
332 public int deleteAll() {
333 return deleteAll(entityClass.getName());
334 }
335
336
337
338
339
340
341
342 public List<E> deleteAllPreFetched() {
343 List<E> entities = list();
344 for (E e : entities) {
345 delete(e);
346 }
347 return entities;
348 }
349
350 @SuppressWarnings("unchecked")
351 protected <T> T execute(CriteriaHibernateCallback<?> criteriaHibernateCallback) {
352 return (T) criteriaHibernateCallback.doInHibernate(getCurrentSession());
353 }
354
355 private SessionFactoryImpl getSessionFactoryImplementor() {
356 return (SessionFactoryImpl) sessionFactory;
357 }
358
359 private static Restrictions.Restriction[] createArrayOfEqualRestrictions(int size) {
360 Restrictions.Restriction[] restrictions = new Restrictions.Restriction[size];
361 Arrays.fill(restrictions, equal());
362 return restrictions;
363 }
364
365
366
367
368
369
370
371
372
373
374
375
376 private static class CriteriaHibernateCallback<T> {
377
378 private final String[] properties;
379 private final Object[] values;
380 private final Restrictions.Restriction[] restrictions;
381 private final Partition partition;
382 private final SessionFactoryImpl implementor;
383 private final List<Order> orders = new ArrayList<Order>();
384 private final Class<?> entityClass;
385 private boolean isUnique;
386 private boolean returnCount;
387 private boolean returnNothing;
388
389
390
391
392
393
394
395
396
397
398
399
400
401 public CriteriaHibernateCallback(Class<?> entityClass, String properties[], Restrictions.Restriction[] restrictions, Object values[], Partition partition, SessionFactoryImpl implementor) {
402 this.entityClass = entityClass;
403 this.partition = partition;
404 this.implementor = implementor;
405 this.properties = properties.clone();
406 this.values = values.clone();
407 this.restrictions = restrictions.clone();
408 }
409
410 public CriteriaHibernateCallback(Class<?> entityClass, String properties[], Restrictions.Restriction[] restrictions, Object values[], SessionFactoryImpl implementor) {
411 this(entityClass, properties, restrictions, values, ALL_IN_ONE_PARTITION, implementor);
412 }
413
414 public CriteriaHibernateCallback(Class<?> entityClass) {
415 this(entityClass, new String[] {}, new Restrictions.Restriction[] {}, new Object[] {}, ALL_IN_ONE_PARTITION, null);
416 }
417
418 public boolean isUnique() {
419 return isUnique;
420 }
421
422
423
424
425 public boolean isReturnCount() {
426 return returnCount;
427 }
428
429 public CriteriaHibernateCallback<T> setReturnCount() {
430 this.returnCount = true;
431 return this;
432 }
433
434 public CriteriaHibernateCallback<T> setUnique() {
435 this.isUnique = true;
436 return this;
437 }
438
439
440
441
442
443
444
445 public CriteriaHibernateCallback<T> addOrder(Order... orders) {
446 this.orders.addAll(Arrays.asList(orders));
447 return this;
448 }
449
450 public final T doInHibernate(Session session) {
451 session.flush();
452 Criteria criteria = session.createCriteria(entityClass);
453 Map<String, Criteria> assosiationPathCriteriaMap = new HashMap<String, Criteria>();
454 applyRestriction(criteria, assosiationPathCriteriaMap);
455 if (!returnNothing) {
456 if (isReturnCount()) {
457 criteria.setProjection(Projections.rowCount());
458 } else {
459 for (Order order : orders) {
460
461
462 creationAssociation(criteria, assosiationPathCriteriaMap, order.getSortedFieldPath()).addOrder(new NullsAwareHibernateOrder(order));
463 }
464 }
465 }
466 return extractResults(criteria);
467 }
468
469 @SuppressWarnings("unchecked")
470 private T extractResults(Criteria criteria) {
471 if (isReturnCount()) {
472 return (T) criteria.uniqueResult();
473 } else if (isUnique()) {
474 return returnNothing ? null : (T) criteria.uniqueResult();
475 }
476 return returnNothing ? (T) Collections.EMPTY_LIST : (T) criteria.list();
477 }
478
479 public void applyRestriction(Criteria criteria, Map<String, Criteria> assosiationPathCriteriaMap) {
480 if (partition.getMax() == 0) {
481 returnNothing = true;
482 return;
483 }
484 criteria.setFirstResult(partition.getFirst()).setMaxResults(partition.getMax());
485
486 for (int i = 0; i < properties.length; i++) {
487 Object value = i < values.length ? values[i] : null;
488 boolean isEmptyCollectionOrArray = ((value instanceof Collection<?>) && ((Collection<?>) value).isEmpty()) || ((value instanceof Object[]) && ((Object[]) value).length == 0);
489 if (restrictions[i] instanceof Restrictions.ExampleRestriction) {
490 criteria.add(createExample(value, (ExampleRestriction) restrictions[i]));
491 if (properties[i].length() == 0) {
492 addAssosiationFilteringByExample(value, criteria, assosiationPathCriteriaMap, "", new HashMap<Class<?>, Set<String>>(), (ExampleRestriction) restrictions[i]);
493 } else {
494
495 Criteria subCriteria = creationAssociation(criteria, assosiationPathCriteriaMap, properties[i]);
496 addAssosiationFilteringByExample(value, subCriteria, assosiationPathCriteriaMap, properties[i], new HashMap<Class<?>, Set<String>>(), (ExampleRestriction) restrictions[i]);
497 }
498 } else if (value != null && !(restrictions[i] instanceof EmptinessAwareRestriction && ((EmptinessAwareRestriction) restrictions[i]).isDisabledIfValueIsEmpty()) && isEmptyCollectionOrArray) {
499 returnNothing = true;
500 criteria.add(org.hibernate.criterion.Restrictions.sqlRestriction("1=0"));
501 return;
502 } else if (!((restrictions[i].isDisabledIfValueIsNull() && value == null) || (restrictions[i] instanceof EmptinessAwareRestriction)
503 && ((EmptinessAwareRestriction) restrictions[i]).isDisabledIfValueIsEmpty() && isEmptyCollectionOrArray)) {
504 Criteria subCriteria = creationAssociation(criteria, assosiationPathCriteriaMap, properties[i]);
505 Criterion criterion = createCriterion(getLastPropertyName(properties[i]), restrictions[i], value);
506 if (restrictions[i] instanceof CaseAwareRestriction && !((CaseAwareRestriction) restrictions[i]).isCaseSensitive()) {
507 ((SimpleExpression) criterion).ignoreCase();
508 }
509 subCriteria.add(criterion);
510 } else {
511
512 }
513 }
514 }
515
516 private Criterion createCriterion(String property, Restrictions.Restriction restriction, Object value) {
517 switch (restriction.getType()) {
518 case LESS:
519 return org.hibernate.criterion.Restrictions.lt(property, value);
520 case LESS_OR_EQUAL:
521 return org.hibernate.criterion.Restrictions.le(property, value);
522 case EQUAL:
523 return org.hibernate.criterion.Restrictions.eq(property, value);
524 case NOT_EQUAL:
525 return org.hibernate.criterion.Restrictions.ne(property, value);
526 case GREATER_OR_EQUAL:
527 return org.hibernate.criterion.Restrictions.ge(property, value);
528 case GREATER:
529 return org.hibernate.criterion.Restrictions.gt(property, value);
530 case LIKE:
531 return org.hibernate.criterion.Restrictions.like(property, value);
532 case ILIKE:
533
534 return new ILikeExpression(property, value.toString());
535
536 case IN:
537 if (value instanceof Collection<?>) {
538 return org.hibernate.criterion.Restrictions.in(property, (Collection<?>) value);
539 } else {
540 return org.hibernate.criterion.Restrictions.in(property, (Object[]) value);
541 }
542 case NOT_IN:
543 return org.hibernate.criterion.Restrictions.not(createCriterion(property, Restrictions.in(), value));
544 case IS_EMPTY:
545 return org.hibernate.criterion.Restrictions.isEmpty(property);
546 case NOT_EMPTY:
547 return org.hibernate.criterion.Restrictions.isNotEmpty(property);
548 case IS_NULL:
549 return org.hibernate.criterion.Restrictions.isNull(property);
550 case NOT_NULL:
551 return org.hibernate.criterion.Restrictions.isNotNull(property);
552 case SIZE_LESS:
553 return org.hibernate.criterion.Restrictions.sizeLt(property, (Integer) value);
554 case SIZE_LESS_OR_EQUAL:
555 return org.hibernate.criterion.Restrictions.sizeLe(property, (Integer) value);
556 case SIZE_EQUAL:
557 return org.hibernate.criterion.Restrictions.sizeEq(property, (Integer) value);
558 case SIZE_GREATER_OR_EQUAL:
559 return org.hibernate.criterion.Restrictions.sizeGe(property, (Integer) value);
560 case SIZE_GREATER:
561 return org.hibernate.criterion.Restrictions.sizeGt(property, (Integer) value);
562 case PROPERTY_LESS:
563 return org.hibernate.criterion.Restrictions.ltProperty(property, (String) value);
564 case PROPERTY_LESS_OR_EQUAL:
565 return org.hibernate.criterion.Restrictions.leProperty(property, (String) value);
566 case PROPERTY_EQUAL:
567 return org.hibernate.criterion.Restrictions.eqProperty(property, (String) value);
568 case PROPERTY_GREATER_OR_EQUAL:
569 return org.hibernate.criterion.Restrictions.geProperty(property, (String) value);
570 case PROPERTY_GREATER:
571 return org.hibernate.criterion.Restrictions.gtProperty(property, (String) value);
572 default:
573 throw new IllegalArgumentException("Unknown restriction=" + restriction + " was passed to method");
574 }
575 }
576
577 private void addAssosiationFilteringByExample(Object example, Criteria criteria, Map<String, Criteria> assosiationPathCriteriaMap, String previousAssosiationPath,
578 Map<Class<?>, Set<String>> entityWalkedProperties, ExampleRestriction exampleRestriction) {
579 Set<String> visitedProperties = entityWalkedProperties.get(example.getClass());
580 if (visitedProperties == null) {
581 visitedProperties = new HashSet<String>();
582 entityWalkedProperties.put(example.getClass(), visitedProperties);
583 }
584 for (String entityName : implementor.getImplementors(example.getClass().getName())) {
585 EntityPersister persister = implementor.getEntityPersister(entityName);
586 for (NonIdentifierAttribute property : persister.getEntityMetamodel().getProperties()) {
587 if (visitedProperties.contains(property.getName())) {
588 continue;
589 }
590 if (property.getType() instanceof CollectionType || property.getType() instanceof ManyToOneType) {
591 visitedProperties.add(property.getName());
592 }
593 Object propertyValue = null;
594 try {
595
596
597 for (PropertyDescriptor propertyDescriptor : Introspector.getBeanInfo(example.getClass()).getPropertyDescriptors()) {
598 if (propertyDescriptor.getName().equals(property.getName())) {
599 propertyValue = propertyDescriptor.getReadMethod().invoke(example);
600 }
601 }
602
603 } catch (Exception e) {
604
605
606 String errorMessage = e.getMessage() + " probably entity " + entityName + " ManyToOne.class annotates a property that has not coresponding public get method";
607 throw new PropertyAccessException(e, errorMessage, false, example.getClass(), property.getName());
608 }
609 if (propertyValue != null) {
610 String newAssosiationPath = previousAssosiationPath + property.getName();
611 Conjunction conjunction = org.hibernate.criterion.Restrictions.conjunction();
612 if (property.getType() instanceof CollectionType) {
613 @SuppressWarnings("unchecked")
614 Collection<Object> collection = (Collection<Object>) propertyValue;
615 if (!collection.isEmpty()) {
616 Criteria subCriteria = criteria.createCriteria(property.getName(), property.getName(), JoinType.LEFT_OUTER_JOIN).add(conjunction);
617 assosiationPathCriteriaMap.put(newAssosiationPath, subCriteria);
618 addAssosiationFilteringByExample(collection.iterator().next(), subCriteria, assosiationPathCriteriaMap, newAssosiationPath + ".", entityWalkedProperties, exampleRestriction);
619 for (Object exampleObject : collection) {
620 conjunction.add(createExample(exampleObject, exampleRestriction));
621 }
622 }
623 } else if (property.getType() instanceof ManyToOneType) {
624 Criteria subCriteria = criteria.createCriteria(property.getName(), property.getName(), JoinType.LEFT_OUTER_JOIN).add(createExample(propertyValue, exampleRestriction));
625 assosiationPathCriteriaMap.put(newAssosiationPath, subCriteria);
626 addAssosiationFilteringByExample(propertyValue, subCriteria, assosiationPathCriteriaMap, newAssosiationPath + ".", entityWalkedProperties, exampleRestriction);
627
628 }
629 }
630
631 }
632 }
633 }
634
635 private static Example createExample(Object object, ExampleRestriction exampleRestriction) {
636 Example example = Example.create(object);
637 if (exampleRestriction.areZeroesExcluded()) {
638 example.excludeZeroes();
639 }
640 if (exampleRestriction.isCaseIgnored()) {
641 example.ignoreCase();
642 }
643 if (exampleRestriction.isLikeEnabled()) {
644 example.enableLike();
645 }
646 if (exampleRestriction.isExcludeNone()) {
647 example.excludeNone();
648 }
649 return example;
650 }
651
652 private static Criteria creationAssosiation(Criteria criteria, Map<String, Criteria> assosiationPathCriteriaMap, String fullAssosiationPath, String previosAssosiationPath) {
653 Criteria subCriteria;
654 int dotIndex = fullAssosiationPath.indexOf('.');
655 if (dotIndex == -1) {
656 subCriteria = criteria;
657 } else {
658 String propertyName = fullAssosiationPath.substring(0, dotIndex);
659 String newAssosiationPath = previosAssosiationPath + propertyName;
660 subCriteria = assosiationPathCriteriaMap.get(newAssosiationPath);
661 if (subCriteria == null) {
662 subCriteria = criteria.createCriteria(propertyName, propertyName, JoinType.LEFT_OUTER_JOIN);
663 assosiationPathCriteriaMap.put(newAssosiationPath, subCriteria);
664 }
665 subCriteria = creationAssosiation(subCriteria, assosiationPathCriteriaMap, fullAssosiationPath.substring(dotIndex + 1), newAssosiationPath + ".");
666 }
667 return subCriteria;
668 }
669
670
671
672
673
674
675
676
677
678 private static Criteria creationAssociation(Criteria criteria, Map<String, Criteria> associationPathCriteriaMap, String fullAssociationPath) {
679 return creationAssosiation(criteria, associationPathCriteriaMap, fullAssociationPath, "");
680 }
681
682 private static String getLastPropertyName(String fullAssosiationPath) {
683 int dotIndex = fullAssosiationPath.lastIndexOf('.');
684 if (dotIndex > -1) {
685 return fullAssosiationPath.substring(dotIndex + 1);
686 }
687 return fullAssosiationPath;
688 }
689
690 private static class NullsAwareHibernateOrder extends org.hibernate.criterion.Order {
691 private static final long serialVersionUID = 3353395213896284011L;
692 private final Order order;
693 private final String propertyName;
694
695 NullsAwareHibernateOrder(final Order order) {
696
697 super(order.getSortedFieldPath(), order.getSortingDirection() == Order.SortingDirection.ASCENDING ? true : false);
698 this.order = order;
699 propertyName = getLastPropertyName(order.getSortedFieldPath());
700 }
701
702 @Override
703 public String toSqlString(Criteria criteria, CriteriaQuery criteriaQuery) throws HibernateException {
704
705 String[] columns = criteriaQuery.getColumnsUsingProjection(criteria, propertyName);
706 Type type = criteriaQuery.getTypeUsingProjection(criteria, propertyName);
707 StringBuilder sql = new StringBuilder();
708 for (int i = 0; i < columns.length; i++) {
709 SessionFactoryImplementor factory = criteriaQuery.getFactory();
710 boolean lower = order.getGetCaseSensitivity() == Order.CaseSensitivity.INSENSITIVE && type.sqlTypes(factory)[i] == Types.VARCHAR;
711 if (lower) {
712 sql.append(factory.getDialect().getLowercaseFunction()).append('(');
713 }
714 sql.append(columns[i]);
715 if (lower) {
716 sql.append(')');
717 }
718 sql.append(order.getSortingDirection() == Order.SortingDirection.ASCENDING ? " asc" : " desc");
719 if (order.getNullsPosition() != Order.NullsPosition.NOT_SPECIFIED) {
720 sql.append(order.getNullsPosition() == Order.NullsPosition.FIRST ? " nulls first" : " nulls last");
721 }
722 if (i < columns.length - 1) {
723 sql.append(", ");
724 }
725 }
726 return sql.toString();
727 }
728 }
729
730 }
731
732
733
734
735
736 private static class ILikeExpression extends LikeExpression {
737
738 private static final long serialVersionUID = 200053570285372152L;
739
740 public ILikeExpression(String propertyName, String value) {
741 super(propertyName, value, null, true);
742 }
743
744 }
745
746
747
748
749 HibernateRepository() {
750 this(null, null);
751 }
752
753 static Partition pageToPartition(Page page) {
754 return new Partition((page.getNumber() - 1) * page.getSize(), page.getSize());
755 }
756
757 }