KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > mlw > vlh > adapter > hibernate3 > HibernateAdapter


1 /**
2  * Copyright (c) 2003 held jointly by the individual authors.
3  *
4  * This library is free software; you can redistribute it and/or modify it
5  * under the terms of the GNU Lesser General Public License as published
6  * by the Free Software Foundation; either version 2.1 of the License, or
7  * (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful, but
10  * WITHOUT ANY WARRANTY; with out even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public License
15  * along with this library; if not, write to the Free Software Foundation,
16  * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
17  *
18  * > http://www.gnu.org/copyleft/lesser.html
19  * > http://www.opensource.org/licenses/lgpl-license.php
20  */

21 package net.mlw.vlh.adapter.hibernate3;
22
23 import java.lang.reflect.InvocationTargetException JavaDoc;
24 import java.text.ParseException JavaDoc;
25 import java.util.ArrayList JavaDoc;
26 import java.util.List JavaDoc;
27
28 import net.mlw.vlh.DefaultListBackedValueList;
29 import net.mlw.vlh.ValueList;
30 import net.mlw.vlh.ValueListInfo;
31 import net.mlw.vlh.adapter.AbstractValueListAdapter;
32 import net.mlw.vlh.adapter.hibernate3.util.ScrollableResultsDecorator;
33 import net.mlw.vlh.adapter.hibernate3.util.StatementBuilder;
34 import net.mlw.vlh.adapter.util.ObjectValidator;
35
36 import org.apache.commons.beanutils.PropertyUtils;
37 import org.apache.commons.logging.Log;
38 import org.apache.commons.logging.LogFactory;
39 import org.hibernate.HibernateException;
40 import org.hibernate.Query;
41 import org.hibernate.ScrollableResults;
42 import org.hibernate.Session;
43 import org.hibernate.SessionFactory;
44 import org.springframework.orm.hibernate3.SessionFactoryUtils;
45
46 /**
47  * This adapter wraps the functionality of Hibernate.
48  * Add extra functionality such as paging, focusing
49  * and validating of current result set.
50  * <i>
51  * "Hibernate is a powerful, ultra-high performance
52  * object/relational persistence and query service
53  * for Java. Hibernate lets you develop persistent
54  * classes following common Java idiom - including
55  * association, inheritance, polymorphism, composition
56  * and the Java collections framework. The Hibernate
57  * Query Language, designed as a "minimal"
58  * object-oriented extension to SQL, provides an
59  * elegant bridge between the object and relational
60  * worlds. Hibernate also allows you to express queries
61  * using native SQL or Java-based Criteria and Example
62  * queries. Hibernate is now the most popular
63  * object/relational mapping solution for Java."
64  * </i> -http://www.hibernate.org/
65  *
66  * @author Matthew L. Wilson, Andrej Zachar
67  * @version $Revision: 1.2 $ $Date: 2006/03/29 19:47:49 $
68  */

69 public class HibernateAdapter extends AbstractValueListAdapter
70 {
71    /** The Hibernate SessionFactory. */
72    private SessionFactory sessionFactory;
73
74    /**
75     * <p>
76     * If is set, it use special ScrollableResultsDecorator, that enable or
77     * disable to add object in final list.
78     * </p>
79     * <h4>NOTE:</h4>
80     * <p>
81     * Also, it respects the total count of entries that overlap your paged
82     * list.
83     * </p>
84     */

85    private ObjectValidator _validator = null;
86
87    /** Commons logger. */
88    private static final Log LOGGER = LogFactory.getLog(HibernateAdapter.class);
89
90    /** If a new Session should be created if no thread-bound found. */
91    private boolean allowCreate = true;
92
93    /** The hibernate query. */
94    private String JavaDoc hql;
95
96    private String JavaDoc namedQuery;
97
98    /** The max rows in ResulSet to doFocus
99     * @author Andrej Zachar
100     */

101    private long maxRowsForFocus = Long.MAX_VALUE;
102
103    /** The name of object use to get focus property in hibernate sql syntax
104     * SELECT defaultFocusPropertyObjectAlias.getFocusProperty ...
105     *
106     * @author Andrej Zachar
107     */

108    private String JavaDoc defaultFocusPropertyObjectAlias = "";
109
110    /**
111     * Enable or Disable String length checking of given filters values. If
112     * filter value is null or empty is removed from query.
113     * @author Andrej Zachar
114     */

115    private boolean _isRemoveEmptyStrings = false;
116
117    private StatementBuilder statementBuilder;
118
119    /**
120     * Enable or disable optimalization of the query for focus property.
121     */

122    private boolean _focusOptimalization = true;
123
124    /**
125     * @return Returns the focusOptimalization.
126     */

127    public boolean isFocusOptimalization()
128    {
129       return _focusOptimalization;
130    }
131
132    /**
133     * Enable or disable optimalization of the query for focus property.
134     * @param focusOptimalization true - enable query with short select, false - query with full select
135     */

136    public void setFocusOptimalization(boolean focusOptimalization)
137    {
138       _focusOptimalization = focusOptimalization;
139    }
140
141    /**
142     * <p>
143     * If is set, it use special ScrollableResultsDecorator, that enable or
144     * disable to add object in final list.
145     * </p>
146     * <h4>NOTE:</h4>
147     * <p>
148     * Also, it respects the total count of entries that overlap your paged
149     * list.
150     * </p>
151     * @param validator The validator to set.
152     */

153    public void setValidator(ObjectValidator validator)
154    {
155       _validator = validator;
156    }
157
158    /**
159     * @return Returns the isPrefilterEmpty.
160     */

161    public boolean isRemoveEmptyStrings()
162    {
163       return _isRemoveEmptyStrings;
164    }
165
166    /**
167     * Enable or Disable String length checking of given filters values. If
168     * filter value is null or empty is removed from query.
169     *
170     * @param isPrefilterEmpty
171     * true-remove null and empty, false - remove only null filters.
172     */

173    public void setRemoveEmptyStrings(boolean isPrefilterEmpty)
174    {
175       _isRemoveEmptyStrings = isPrefilterEmpty;
176    }
177
178    /**
179     * @see net.mlw.vlh.ValueListAdapter#getValueList(java.lang.String,
180     * net.mlw.vlh.ValueListInfo)
181     */

182    public ValueList getValueList(String JavaDoc name, ValueListInfo info)
183    {
184
185       LOGGER.debug("getValueList(String, ValueListInfo) - start");
186
187       if (info.getSortingColumn() == null)
188       {
189          info.setPrimarySortColumn(getDefaultSortColumn());
190          info.setPrimarySortDirection(getDefaultSortDirectionInteger());
191          if (LOGGER.isDebugEnabled())
192          {
193             LOGGER.debug("The default sort column '" + getDefaultSortColumn() + "' with direction '" + getDefaultSortDirectionInteger()
194                   + "' was set.");
195          }
196       }
197
198       int numberPerPage = info.getPagingNumberPer();
199
200       if (numberPerPage == Integer.MAX_VALUE)
201       {
202          numberPerPage = getDefaultNumberPerPage();
203          info.setPagingNumberPer(numberPerPage);
204          if (LOGGER.isDebugEnabled())
205          {
206             LOGGER.debug("The paging number per page '" + numberPerPage + "' was set.");
207          }
208       }
209
210       Session session = SessionFactoryUtils.getSession(getSessionFactory(), allowCreate);
211       try
212       {
213          Query query;
214
215          boolean doFocus = ((getAdapterType() & DO_FOCUS) == 0) && info.isFocusEnabled() && info.isDoFocus() && (namedQuery == null);
216
217          if (doFocus)
218          {
219             if (LOGGER.isDebugEnabled())
220             {
221                LOGGER.debug("Start to focusing adapterName '" + name + "', ValueListInfo info = " + info + "'");
222             }
223             ScrollableResults results = getScrollableResults(getQueryForFocus(info, session), info);
224             results.beforeFirst();
225             doFocusFor(info, results);
226
227             if (LOGGER.isDebugEnabled())
228             {
229                LOGGER.debug("Focusing finished for adapterName '" + name + "', ValueListInfo info '" + info + "'");
230             }
231          }
232
233          query = getQuery(info, session);
234
235          boolean doPaging = ((getAdapterType() & DO_PAGE) == 0);
236
237          List JavaDoc list;
238
239          if (doPaging)
240          {
241             if (LOGGER.isDebugEnabled())
242             {
243                LOGGER.debug("getValueList(String adapterName = " + name + ", ValueListInfo info = " + info
244                      + ") - Start to paging result set");
245             }
246
247             list = new ArrayList JavaDoc(numberPerPage);
248             ScrollableResults results = getScrollableResults(query, info);
249
250             results.last();
251             int lastRowNumber = results.getRowNumber();
252             info.setTotalNumberOfEntries(lastRowNumber + 1);
253
254             if (numberPerPage == 0)
255             {
256                numberPerPage = getDefaultNumberPerPage();
257             }
258
259             int pageNumber = info.getPagingPage();
260             boolean isResult;
261             if (pageNumber > 1)
262             {
263                if ((pageNumber - 1) * numberPerPage > lastRowNumber)
264                {
265                   pageNumber = (lastRowNumber / numberPerPage) + 1;
266                   info.setPagingPage(pageNumber);
267                }
268             }
269             if (pageNumber > 1)
270             {
271                isResult = results.scroll((pageNumber - 1) * numberPerPage - lastRowNumber);
272             }
273             else
274             {
275                isResult = results.first();
276             }
277
278             for (int i = 0; i < numberPerPage && isResult; i++)
279             {
280                list.add(results.get(0));
281                isResult = results.next();
282             }
283
284             LOGGER.debug("Sorting finished.");
285
286          }
287          else
288          {
289
290             LOGGER.debug("Retrieving a list directly from the query.");
291
292             list = query.list();
293             info.setTotalNumberOfEntries(list.size());
294          }
295
296          ValueList returnValueList = getListBackedValueList(info, list);
297          if (LOGGER.isDebugEnabled())
298          {
299             LOGGER.debug("Retrieved list was wrapped in valuelist, info=" + info);
300          }
301          return returnValueList;
302       }
303       catch (HibernateException e)
304       {
305          LOGGER.error("Error getting data in adapater '" + name + "' with info = '" + info + "'", e);
306          throw SessionFactoryUtils.convertHibernateAccessException(e);
307       }
308       catch (Exception JavaDoc e)
309       {
310          LOGGER.fatal("Fatal error getting data in adapater '" + name + "' with info = '" + info + "'", e);
311          return null;
312       }
313       finally
314       {
315          SessionFactoryUtils.releaseSession(session, getSessionFactory());
316       }
317    }
318
319    /**
320     * @param info
321     * @param list
322     * @return DefaultListBackValueList instance
323     */

324    protected ValueList getListBackedValueList(ValueListInfo info, List JavaDoc list)
325    {
326       return new DefaultListBackedValueList(list, info);
327    }
328
329    /**
330     * @param info
331     * @param results
332     * @throws HibernateException
333     * @throws NoSuchMethodException
334     * @throws InvocationTargetException
335     * @throws IllegalAccessException
336     */

337    private void doFocusFor(ValueListInfo info, ScrollableResults results) throws HibernateException
338    {
339       info.setFocusStatus(ValueListInfo.FOCUS_NOT_FOUND);
340
341       int currentRow;
342       if (isFocusOptimalization())
343       {
344          if (LOGGER.isDebugEnabled())
345          {
346             LOGGER.debug("Focusing only property '" + info.getFocusProperty() + "' == '" + info.getFocusValue() + "'.");
347          }
348          for (currentRow = 0; ((results.next()) && (currentRow < maxRowsForFocus)); currentRow++)
349          {
350             String JavaDoc value = results.get(0).toString();
351             if (value.equalsIgnoreCase(info.getFocusValue()))
352             {
353                if (LOGGER.isInfoEnabled())
354                {
355                   LOGGER.info("Focus property '" + info.getFocusProperty() + "' in row '" + currentRow + "'.");
356                }
357                info.setPagingPageFromRowNumber(results.getRowNumber());
358                info.setFocusedRowNumberInTable(results.getRowNumber());
359                info.setFocusStatus(ValueListInfo.FOCUS_FOUND);
360                break;
361             }
362          }
363       }
364       else
365       {
366          if (LOGGER.isDebugEnabled())
367          {
368             LOGGER.debug("Focusing object with the property '" + info.getFocusProperty() + "' == '" + info.getFocusValue() + "'.");
369          }
370          for (currentRow = 0; ((results.next()) && (currentRow < maxRowsForFocus)); currentRow++)
371          {
372
373             Object JavaDoc value;
374             try
375             {
376                value = PropertyUtils.getProperty(results.get(0), info.getFocusProperty());
377             }
378             catch (HibernateException e)
379             {
380                LOGGER.error("Error getting focus property '" + info.getFocusProperty() + "'", e);
381                throw e;
382             }
383             catch (Exception JavaDoc e)
384             {
385                LOGGER.warn("Ingoring error while getting focus property '" + info.getFocusProperty() + "'", e);
386                continue;
387             }
388
389             if (value.toString().equalsIgnoreCase(info.getFocusValue()))
390             {
391                if (LOGGER.isInfoEnabled())
392                {
393                   LOGGER.info("Focus object's property '" + info.getFocusProperty() + "' was found in the row '" + currentRow + "'.");
394                }
395                info.setPagingPageFromRowNumber(results.getRowNumber());
396                info.setFocusedRowNumberInTable(results.getRowNumber());
397                info.setFocusStatus(ValueListInfo.FOCUS_FOUND);
398                break;
399             }
400          }
401       }
402       if (currentRow == maxRowsForFocus)
403       {
404          if (LOGGER.isInfoEnabled())
405          {
406             LOGGER.info("Focus for property '" + info.getFocusProperty() + "' exceded maximum rows for focus '" + maxRowsForFocus + "'.");
407          }
408          info.setFocusStatus(ValueListInfo.FOCUS_TOO_MANY_ITEMS);
409       }
410    }
411
412    /**
413     * @param query
414     * @param info ValueListInfo This info will be set to validator.
415     * @return ScrollableResults, if is set non null _validator, it returns the
416     * ScrollableResultsDecorator.
417     * @throws HibernateException
418     */

419    private ScrollableResults getScrollableResults(Query query, ValueListInfo info) throws HibernateException
420    {
421       ScrollableResults results;
422
423       if (_validator == null)
424       {
425          LOGGER.debug("Validator is null, using normal ScrollableResults");
426          results = query.scroll();
427
428       }
429       else
430       {
431          LOGGER.info("Using decorator of the ScrollableResults with your validator.");
432          _validator.setValueListInfo(info);
433          results = new ScrollableResultsDecorator(query.scroll(), _validator);
434       }
435
436       return results;
437    }
438
439    /**
440     * @param info
441     * @param session
442     * @return @throws
443     * HibernateException
444     */

445    private Query getQuery(ValueListInfo info, Session session) throws HibernateException, ParseException JavaDoc
446    {
447
448       if (getHql() != null)
449       {
450          return getStatementBuilder().generate(session, new StringBuffer JavaDoc(getHql()), info.getFilters(), _isRemoveEmptyStrings);
451       }
452       else
453       {
454          if (namedQuery != null)
455          {
456             return session.getNamedQuery(getNamedQuery());
457          }
458          else
459          {
460             throw new HibernateException("Please define any QUERY in value list retrieve adpater!");
461          }
462       }
463    }
464
465    /**
466     * If focus optimalization is true, it select only focus property. For
467     * validator is recommended to set it to false, while you want to validate
468     * properties of retrieved objects.
469     *
470     * @param info
471     * @param session
472     * @return
473     * @throws HibernateException
474     */

475    private Query getQueryForFocus(ValueListInfo info, Session session) throws HibernateException, ParseException JavaDoc
476    {
477       if (isFocusOptimalization())
478       {
479          LOGGER.info("Focus will use optimalizated query.");
480          return getOptimizedQuery(info, session);
481       }
482       else
483       {
484          LOGGER.info("Focus will use normal (full) query.");
485          return getQuery(info, session);
486       }
487    }
488
489    /**
490     *
491     * @param info
492     * @param session
493     * @return query that select only focus property.
494     * @throws HibernateException
495     * @throws ParseException
496     */

497    private Query getOptimizedQuery(ValueListInfo info, Session session) throws HibernateException, ParseException JavaDoc
498    {
499       if (getHql() != null)
500       {
501          return getStatementBuilder().generateForFocus(session, new StringBuffer JavaDoc(getHql()), info.getFilters(), _isRemoveEmptyStrings,
502                defaultFocusPropertyObjectAlias, info.getFocusProperty());
503
504       }
505       else
506       {
507          throw new HibernateException(
508                "Please define any HQL QUERY in value list retrieve adpater, function is not implemented for NamedQuery!");
509       }
510    }
511
512    /** Set the Hibernate SessionFactory to be used by this DAO.
513     *
514     * @param sessionFactory The Hibernate SessionFactory to be used by this DAO.
515     */

516    public final void setSessionFactory(SessionFactory sessionFactory)
517    {
518       this.sessionFactory = sessionFactory;
519    }
520
521    /** Return the Hibernate SessionFactory used by this DAO.
522     *
523     * @return The Hibernate SessionFactory used by this DAO.
524     */

525    protected final SessionFactory getSessionFactory()
526    {
527       return this.sessionFactory;
528    }
529
530    /** Sets the hql used to retrieve the data.
531     * @param hql The hql to set.
532     * @deprecated use setHql(String)
533     */

534    public void setHsql(String JavaDoc hql)
535    {
536       this.hql = hql;
537    }
538
539    /** Sets the hql used to retrieve the data.
540     * @param hql The hql to set.
541     */

542    public void setHql(String JavaDoc hql)
543    {
544       this.hql = hql;
545    }
546
547    /** Returns the namedQuery.
548     * @return Returns the namedQuery.
549     */

550    public String JavaDoc getNamedQuery()
551    {
552       return namedQuery;
553    }
554
555    /** Sets the namedQuery.
556     * <p>
557     * NOTE: by using this you can not enable sorting, filtering,
558     * paging of the data, and focusing of rows.
559     * </p>
560     * @param namedQuery
561     * The namedQuery to set.
562     */

563    public void setNamedQuery(String JavaDoc namedQuery)
564    {
565       this.namedQuery = namedQuery;
566    }
567
568    /** Gets the hql used to retrieve the data.
569     * @return Returns the hql.
570     */

571    public String JavaDoc getHql()
572    {
573       return hql;
574    }
575
576    /** Sets: If a new Session should be created if no thread-bound found.
577     *
578     * @param allowCreate
579     * The allowCreate to set.
580     */

581    public void setAllowCreate(boolean allowCreate)
582    {
583       this.allowCreate = allowCreate;
584    }
585
586    /**
587     * Maximum rows to search with Focus
588     *
589     * @return Returns the maxRowsForFocus.
590     */

591    public long getMaxRowsForFocus()
592    {
593       return maxRowsForFocus;
594    }
595
596    /**
597     * Maximum rows to search with Focus
598     *
599     * @param maxRowsForFocus
600     * The maxRowsForFocus to set.
601     */

602    public void setMaxRowsForFocus(long maxRowsForFocus)
603    {
604       this.maxRowsForFocus = maxRowsForFocus;
605    }
606
607    /**
608     * @return Returns the defaultFocusPropertyObject.
609     */

610    public String JavaDoc getDefaultFocusPropertyObjectAlias()
611    {
612       return defaultFocusPropertyObjectAlias;
613    }
614
615    /**
616     * The name of object use to get focus property in hibernate hql syntax
617     * SELECT defaultFocusPropertyObjectAlias.getFocusProperty ...
618     *
619     * @param defaultFocusPropertyObjectAlias
620     * The defaultFocusPropertyObjectAlias to set.
621     */

622    public void setDefaultFocusPropertyObjectAlias(String JavaDoc defaultFocusPropertyObjectAlias)
623    {
624       this.defaultFocusPropertyObjectAlias = defaultFocusPropertyObjectAlias + ".";
625    }
626
627    /**
628     * @return Returns the statementBuilder.
629     */

630    public StatementBuilder getStatementBuilder()
631    {
632       if (statementBuilder == null)
633       {
634          statementBuilder = new StatementBuilder();
635       }
636       return statementBuilder;
637    }
638
639    /**
640     * @param statementBuilder The statementBuilder to set.
641     */

642    public void setStatementBuilder(StatementBuilder statementBuilder)
643    {
644       this.statementBuilder = statementBuilder;
645    }
646 }
Popular Tags