2 * This is a common dao with basic CRUD operations and is not limited to any
3 * persistent layer implementation
5 * Copyright (C) 2008 Imran M Yousuf (imyousuf@smartitengineering.com)
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 3 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 package com
.smartitengineering
.dao
.impl
.hibernate
;
21 import com
.smartitengineering
.dao
.common
.queryparam
.BasicCompoundQueryParameter
;
22 import com
.smartitengineering
.dao
.common
.queryparam
.BiOperandQueryParameter
;
23 import com
.smartitengineering
.dao
.common
.queryparam
.CompositionQueryParameter
;
24 import com
.smartitengineering
.dao
.common
.queryparam
.OperatorType
;
25 import com
.smartitengineering
.dao
.common
.queryparam
.QueryParameter
;
26 import com
.smartitengineering
.dao
.common
.queryparam
.QueryParameterCastHelper
;
27 import com
.smartitengineering
.dao
.common
.queryparam
.QueryParameterWithOperator
;
28 import com
.smartitengineering
.dao
.common
.queryparam
.QueryParameterWithPropertyName
;
29 import com
.smartitengineering
.dao
.common
.queryparam
.QueryParameterWithValue
;
30 import com
.smartitengineering
.dao
.common
.queryparam
.SimpleNameValueQueryParameter
;
31 import com
.smartitengineering
.dao
.common
.queryparam
.ValueOnlyQueryParameter
;
32 import com
.smartitengineering
.domain
.PersistentDTO
;
33 import java
.io
.Serializable
;
34 import java
.util
.Collection
;
35 import java
.util
.Hashtable
;
36 import java
.util
.List
;
39 import java
.util
.WeakHashMap
;
40 import org
.hibernate
.Criteria
;
41 import org
.hibernate
.FetchMode
;
42 import org
.hibernate
.Session
;
43 import org
.hibernate
.criterion
.AggregateProjection
;
44 import org
.hibernate
.criterion
.Conjunction
;
45 import org
.hibernate
.criterion
.CountProjection
;
46 import org
.hibernate
.criterion
.Criterion
;
47 import org
.hibernate
.criterion
.Disjunction
;
48 import org
.hibernate
.criterion
.Expression
;
49 import org
.hibernate
.criterion
.Junction
;
50 import org
.hibernate
.criterion
.MatchMode
;
51 import org
.hibernate
.criterion
.Order
;
52 import org
.hibernate
.criterion
.Projection
;
53 import org
.hibernate
.criterion
.ProjectionList
;
54 import org
.hibernate
.criterion
.Projections
;
55 import org
.hibernate
.criterion
.PropertyProjection
;
56 import org
.hibernate
.criterion
.Restrictions
;
57 import org
.springframework
.orm
.hibernate3
.support
.HibernateDaoSupport
;
59 public abstract class AbstractDAO
<Template
extends PersistentDTO
>
60 extends HibernateDaoSupport
61 implements Serializable
{
63 private Map
<Criteria
, ProjectionList
> projections
=
64 new WeakHashMap
<Criteria
, ProjectionList
>();
66 protected void createEntity(Template
... entities
) {
67 if (entities
== null) {
68 throw new IllegalArgumentException();
71 boolean customSession
= false;
73 session
= getSessionFactory().getCurrentSession();
75 catch (Exception ex
) {
76 session
= getSessionFactory().openSession();
80 for (Template entity
: entities
) {
85 if (session
!= null) {
87 if (customSession
&& session
.isOpen()) {
94 protected void updateEntity(Template
... entities
) {
95 if (entities
== null) {
96 throw new IllegalArgumentException();
99 boolean customSession
= false;
101 session
= getSessionFactory().getCurrentSession();
103 catch (Exception ex
) {
104 session
= getSessionFactory().openSession();
105 customSession
= true;
108 for (Template entity
: entities
) {
109 session
.update(entity
);
113 if (session
!= null) {
115 if (customSession
&& session
.isOpen()) {
122 protected void deleteEntity(Template
... entities
) {
123 if (entities
== null) {
124 throw new IllegalArgumentException();
127 boolean customSession
= false;
129 session
= getSessionFactory().getCurrentSession();
131 catch (Exception ex
) {
132 session
= getSessionFactory().openSession();
133 customSession
= true;
136 for (Template entity
: entities
) {
137 session
.delete(entity
);
141 if (session
!= null) {
143 if (customSession
&& session
.isOpen()) {
150 protected Template
readSingle(Class entityClass
,
151 Hashtable
<String
, QueryParameter
> parameter
) {
152 return readSingle(entityClass
, parameter
.values().toArray(
153 new QueryParameter
[0]));
156 protected Object
readOther(Class entityClass
,
157 Hashtable
<String
, QueryParameter
> parameter
) {
158 return readOther(entityClass
, parameter
.values().toArray(
159 new QueryParameter
[0]));
162 protected List
<?
extends Object
> readOtherList(Class entityClass
,
163 Hashtable
<String
, QueryParameter
> parameter
) {
164 return readOtherList(entityClass
, parameter
.values().toArray(
165 new QueryParameter
[0]));
168 protected List
<Template
> readList(Class entityClass
,
169 Hashtable
<String
, QueryParameter
> parameter
) {
170 return readList(entityClass
, parameter
.values().toArray(
171 new QueryParameter
[0]));
174 protected Template
readSingle(Class entityClass
,
175 List
<QueryParameter
> parameter
) {
176 return readSingle(entityClass
, parameter
.toArray(new QueryParameter
[0]));
179 protected <OtherTemplate
extends Object
> OtherTemplate
readOther(
181 List
<QueryParameter
> parameter
) {
182 return this.<OtherTemplate
>readOther(entityClass
, parameter
.toArray(new QueryParameter
[0]));
185 protected <OtherTemplate
extends Object
> List
<OtherTemplate
> readOtherList(
187 List
<QueryParameter
> parameter
) {
188 return readOtherList(entityClass
, parameter
.toArray(
189 new QueryParameter
[0]));
192 protected List
<Template
> readList(Class entityClass
,
193 List
<QueryParameter
> parameter
) {
194 return readList(entityClass
, parameter
.toArray(new QueryParameter
[0]));
197 protected Template
readSingle(Class entityClass
,
198 QueryParameter
... parameter
) {
200 boolean customSession
= false;
202 session
= getSessionFactory().getCurrentSession();
204 catch (Exception ex
) {
205 session
= getSessionFactory().openSession();
206 customSession
= true;
209 Criteria criteria
= simpleSearchCriteria(session
, entityClass
,
211 return (Template
) criteria
.uniqueResult();
213 catch (Exception e
) {
214 throw new IllegalArgumentException(e
);
217 if (session
!= null) {
218 if (customSession
&& session
.isOpen()) {
225 protected <OtherTemplate
extends Object
> OtherTemplate
readOther(
227 QueryParameter
... parameter
) {
229 boolean customSession
= false;
231 session
= getSessionFactory().getCurrentSession();
233 catch (Exception ex
) {
234 session
= getSessionFactory().openSession();
235 customSession
= true;
238 Criteria criteria
= simpleSearchCriteria(session
, entityClass
,
240 return (OtherTemplate
) criteria
.uniqueResult();
242 catch (Exception e
) {
243 throw new IllegalArgumentException(e
);
246 if (session
!= null) {
247 if (customSession
&& session
.isOpen()) {
254 protected <OtherTemplate
extends Object
> List
<OtherTemplate
> readOtherList(
256 QueryParameter
... parameter
) {
258 boolean customSession
= false;
260 session
= getSessionFactory().getCurrentSession();
262 catch (Exception ex
) {
263 session
= getSessionFactory().openSession();
264 customSession
= true;
267 Criteria criteria
= simpleSearchCriteria(session
, entityClass
,
269 return criteria
.list();
271 catch (Exception e
) {
272 throw new IllegalArgumentException(e
);
275 if (session
!= null) {
276 if (customSession
&& session
.isOpen()) {
283 protected List
<Template
> readList(Class entityClass
,
284 QueryParameter
... parameter
) {
286 boolean customSession
= false;
288 session
= getSessionFactory().getCurrentSession();
290 catch (Exception ex
) {
291 session
= getSessionFactory().openSession();
292 customSession
= true;
295 Criteria criteria
= simpleSearchCriteria(session
, entityClass
,
297 return criteria
.list();
299 catch (Exception e
) {
300 throw new IllegalArgumentException(e
);
303 if (session
!= null) {
304 if (customSession
&& session
.isOpen()) {
311 protected Criteria
simpleSearchCriteria(Session session
,
313 QueryParameter
... parameter
) {
314 Criteria criteria
= session
.createCriteria(queryClass
);
315 for (QueryParameter param
: parameter
) {
316 if (!param
.isInitialized()) {
319 String propertyName
= getPropertyName(param
);
320 processCriteria(criteria
, propertyName
, param
);
325 @SuppressWarnings("unchecked")
326 private void processCriteria(Criteria criteria
,
328 QueryParameter parameter
) {
329 switch (parameter
.getParameterType()) {
330 case PARAMETER_TYPE_PROPERTY
: {
331 criteria
.add(getCriterion(element
, parameter
));
334 case PARAMETER_TYPE_ORDER_BY
: {
336 SimpleNameValueQueryParameter
<com
.smartitengineering
.dao
.common
.queryparam
.Order
> queryParameter
=
337 QueryParameterCastHelper
.SIMPLE_PARAM_HELPER
.cast(parameter
);
338 com
.smartitengineering
.dao
.common
.queryparam
.Order requestedOrder
=
339 queryParameter
.getValue();
340 switch (requestedOrder
) {
342 order
= Order
.asc(element
);
346 order
= Order
.desc(element
);
355 criteria
.addOrder(order
);
359 case PARAMETER_TYPE_MAX_RESULT
: {
360 ValueOnlyQueryParameter
<Integer
> queryParameter
=
361 QueryParameterCastHelper
.VALUE_PARAM_HELPER
.cast(parameter
);
362 criteria
.setMaxResults(queryParameter
.getValue());
365 case PARAMETER_TYPE_FIRST_RESULT
: {
366 ValueOnlyQueryParameter
<Integer
> queryParameter
=
367 QueryParameterCastHelper
.VALUE_PARAM_HELPER
.cast(parameter
);
368 criteria
.setFirstResult(queryParameter
.getValue());
371 case PARAMETER_TYPE_DISJUNCTION
: {
372 processDisjunction(criteria
, parameter
);
375 case PARAMETER_TYPE_CONJUNCTION
: {
376 processConjunction(criteria
, parameter
);
379 case PARAMETER_TYPE_NESTED_PROPERTY
: {
380 processNestedParameter(criteria
, element
, parameter
);
383 case PARAMETER_TYPE_COUNT
: {
384 final Projection countProjection
= Projections
.count(element
);
385 setProjection(criteria
, countProjection
);
388 case PARAMETER_TYPE_ROW_COUNT
: {
389 final Projection rowCount
= Projections
.rowCount();
390 setProjection(criteria
, rowCount
);
393 case PARAMETER_TYPE_SUM
: {
394 final AggregateProjection sum
= Projections
.sum(element
);
395 setProjection(criteria
, sum
);
398 case PARAMETER_TYPE_MAX
: {
399 final AggregateProjection max
= Projections
.max(element
);
400 setProjection(criteria
, max
);
403 case PARAMETER_TYPE_MIN
: {
404 final AggregateProjection min
= Projections
.min(element
);
405 setProjection(criteria
, min
);
408 case PARAMETER_TYPE_AVG
: {
409 final AggregateProjection avg
= Projections
.avg(element
);
410 setProjection(criteria
, avg
);
413 case PARAMETER_TYPE_GROUP_BY
: {
414 final PropertyProjection groupProperty
=
415 Projections
.groupProperty(element
);
416 setProjection(criteria
, groupProperty
);
419 case PARAMETER_TYPE_COUNT_DISTINCT
: {
420 final CountProjection countDistinct
=
421 Projections
.countDistinct(element
);
422 setProjection(criteria
, countDistinct
);
425 case PARAMETER_TYPE_DISTINCT_PROP
: {
426 final Projection distinct
=
427 Projections
.distinct(Projections
.property(element
));
428 setProjection(criteria
, distinct
);
431 case PARAMETER_TYPE_UNIT_PROP
: {
432 final PropertyProjection property
=
433 Projections
.property(element
);
434 setProjection(criteria
, property
);
440 @SuppressWarnings("unchecked")
441 private void processNestedParameter(Criteria criteria
,
443 QueryParameter parameter
) {
445 CompositionQueryParameter queryParameter
=
446 QueryParameterCastHelper
.COMPOSITION_PARAM_FOR_NESTED_TYPE
.cast(
448 switch (queryParameter
.getFetchMode()) {
450 mode
= FetchMode
.EAGER
;
453 mode
= FetchMode
.SELECT
;
456 mode
= FetchMode
.JOIN
;
459 mode
= FetchMode
.LAZY
;
463 mode
= FetchMode
.DEFAULT
;
466 criteria
.setFetchMode(element
, ((mode
== null) ? FetchMode
.JOIN
: mode
));
467 Collection
<QueryParameter
> nestedParameters
= queryParameter
.
468 getNestedParameters();
469 if (nestedParameters
== null || nestedParameters
.size() <= 0) {
472 Criteria nestedCriteria
= criteria
.createCriteria(element
);
473 for (QueryParameter nestedQueryParameter
: nestedParameters
) {
474 if (!nestedQueryParameter
.isInitialized()) {
477 processCriteria(nestedCriteria
,
478 getPropertyName(nestedQueryParameter
), nestedQueryParameter
);
482 @SuppressWarnings("unchecked")
483 private void processCriterion(Junction criterion
,
485 QueryParameter parameter
) {
486 switch (parameter
.getParameterType()) {
487 case PARAMETER_TYPE_PROPERTY
: {
488 criterion
.add(getCriterion(element
, parameter
));
491 case PARAMETER_TYPE_CONJUNCTION
: {
492 processConjunction(criterion
, parameter
);
495 case PARAMETER_TYPE_DISJUNCTION
: {
496 processDisjunction(criterion
, parameter
);
503 @SuppressWarnings("unchecked")
504 private void processDisjunction(Criteria criteria
,
505 QueryParameter parameter
) {
506 Disjunction disjunction
= Expression
.disjunction();
507 workOnNestedParams(parameter
, disjunction
);
508 criteria
.add(disjunction
);
511 @SuppressWarnings("unchecked")
512 private void processConjunction(Criteria criteria
,
513 QueryParameter parameter
) {
514 Conjunction conjunction
= Expression
.conjunction();
515 workOnNestedParams(parameter
, conjunction
);
516 criteria
.add(conjunction
);
519 @SuppressWarnings("unchecked")
520 private void processDisjunction(Junction junction
,
521 QueryParameter parameter
) {
522 Disjunction disjunction
= Expression
.disjunction();
523 workOnNestedParams(parameter
, disjunction
);
524 junction
.add(disjunction
);
527 @SuppressWarnings("unchecked")
528 private void processConjunction(Junction junction
,
529 QueryParameter parameter
) {
530 Conjunction conjunction
= Expression
.conjunction();
531 workOnNestedParams(parameter
, conjunction
);
532 junction
.add(conjunction
);
535 private Criterion
getCriterion(String element
,
536 QueryParameter queryParamemter
) {
537 OperatorType operator
= getOperator(queryParamemter
);
538 Object parameter
= getValue(queryParamemter
);
540 case OPERATOR_EQUAL
: {
541 return Expression
.eq(element
, parameter
);
543 case OPERATOR_LESSER
: {
544 return Expression
.lt(element
, parameter
);
546 case OPERATOR_LESSER_EQUAL
: {
547 return Expression
.le(element
, parameter
);
549 case OPERATOR_GREATER
: {
550 return Expression
.gt(element
, parameter
);
552 case OPERATOR_GREATER_EQUAL
: {
553 return Expression
.ge(element
, parameter
);
555 case OPERATOR_NOT_EQUAL
: {
556 return Expression
.ne(element
, parameter
);
558 case OPERATOR_IS_NULL
: {
559 return Expression
.isNull(element
);
561 case OPERATOR_IS_NOT_NULL
: {
562 return Expression
.isNotNull(element
);
564 case OPERATOR_IS_EMPTY
: {
565 return Expression
.isEmpty(element
);
567 case OPERATOR_IS_NOT_EMPTY
: {
568 return Expression
.isNotEmpty(element
);
570 case OPERATOR_STRING_LIKE
: {
571 MatchMode hibernateMatchMode
;
572 com
.smartitengineering
.dao
.common
.queryparam
.MatchMode matchMode
=
573 getMatchMode(queryParamemter
);
574 if (matchMode
== null) {
576 com
.smartitengineering
.dao
.common
.queryparam
.MatchMode
.EXACT
;
580 hibernateMatchMode
= MatchMode
.END
;
583 hibernateMatchMode
= MatchMode
.EXACT
;
586 hibernateMatchMode
= MatchMode
.START
;
590 hibernateMatchMode
= MatchMode
.ANYWHERE
;
593 return Expression
.like(element
, parameter
.toString(),
596 case OPERATOR_BETWEEN
: {
597 parameter
= getFirstParameter(queryParamemter
);
598 Object parameter2
= getSecondParameter(queryParamemter
);
599 return Expression
.between(element
, parameter
, parameter2
);
601 case OPERATOR_IS_IN
: {
602 Collection inCollectin
=
603 QueryParameterCastHelper
.MULTI_OPERAND_PARAM_HELPER
.cast(
604 queryParamemter
).getValues();
605 return Restrictions
.in(element
, inCollectin
);
607 case OPERATOR_IS_NOT_IN
: {
608 Collection inCollectin
=
609 QueryParameterCastHelper
.MULTI_OPERAND_PARAM_HELPER
.cast(
610 queryParamemter
).getValues();
611 return Restrictions
.not(Restrictions
.in(element
, inCollectin
));
617 private String
getPropertyName(
618 QueryParameter param
) {
619 final String propertyName
;
621 if (param
instanceof QueryParameterWithPropertyName
) {
623 ((QueryParameterWithPropertyName
) param
).getPropertyName();
632 private void setProjection(Criteria criteria
,
633 final Projection projection
) {
634 ProjectionList currentProjections
= projections
.get(
636 if (currentProjections
== null) {
637 currentProjections
= Projections
.projectionList();
638 projections
.put(criteria
, currentProjections
);
639 criteria
.setProjection(currentProjections
);
642 currentProjections
.add(projection
);
645 private void workOnNestedParams(QueryParameter parameter
,
646 Junction criterion
) {
647 BasicCompoundQueryParameter queryParameter
=
648 QueryParameterCastHelper
.BASIC_COMPOUND_PARAM_HELPER
.cast(parameter
);
649 Collection
<QueryParameter
> nestedParameters
=
650 queryParameter
.getNestedParameters();
651 for (QueryParameter nestedParam
: nestedParameters
) {
652 if (!nestedParam
.isInitialized()) {
655 processCriterion(criterion
, getPropertyName(nestedParam
),
661 private OperatorType
getOperator(QueryParameter queryParamemter
) {
662 if (QueryParameterCastHelper
.BASIC_COMPOUND_PARAM_HELPER
.isWithOperator(
664 QueryParameterWithOperator parameterWithOperator
=
665 QueryParameterCastHelper
.BI_OPERAND_PARAM_HELPER
.
668 return parameterWithOperator
.getOperatorType();
675 private Object
getValue(QueryParameter queryParamemter
) {
677 if (queryParamemter
instanceof QueryParameterWithValue
) {
678 value
= ((QueryParameterWithValue
) queryParamemter
).getValue();
689 private Object
getSecondParameter(QueryParameter queryParamemter
) {
690 if (queryParamemter
instanceof BiOperandQueryParameter
) {
691 return QueryParameterCastHelper
.BI_OPERAND_PARAM_HELPER
.cast(
692 queryParamemter
).getSecondValue();
699 private Object
getFirstParameter(QueryParameter queryParamemter
) {
700 if (queryParamemter
instanceof BiOperandQueryParameter
) {
701 return QueryParameterCastHelper
.BI_OPERAND_PARAM_HELPER
.cast(
702 queryParamemter
).getFirstValue();
709 private com
.smartitengineering
.dao
.common
.queryparam
.MatchMode
getMatchMode(
710 QueryParameter queryParamemter
) {
711 return QueryParameterCastHelper
.STRING_PARAM_HELPER
.cast(queryParamemter
).