KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > net > mlw > vlh > adapter > hibernate > Hibernate20Adapter


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.hibernate;
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.hibernate.util.ScrollableResultsDecorator;
33 import net.mlw.vlh.adapter.hibernate.util.StatementBuilder;
34 import net.mlw.vlh.adapter.util.ObjectValidator;
35 import net.sf.hibernate.HibernateException;
36 import net.sf.hibernate.Query;
37 import net.sf.hibernate.ScrollableResults;
38 import net.sf.hibernate.Session;
39 import net.sf.hibernate.SessionFactory;
40
41 import org.apache.commons.beanutils.PropertyUtils;
42 import org.apache.commons.logging.Log;
43 import org.apache.commons.logging.LogFactory;
44 import org.springframework.orm.hibernate.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.27 $ $Date: 2006/03/29 19:47:48 $
68  */

69 public class Hibernate20Adapter 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(Hibernate20Adapter.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          // deprecated since spring 1.2
316
SessionFactoryUtils.closeSessionIfNecessary(session, getSessionFactory());
317       }
318    }
319
320    /**
321     * @param info
322     * @param list
323     * @return DefaultListBackValueList instance
324     */

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

645    public void setStatementBuilder(StatementBuilder statementBuilder)
646    {
647       this.statementBuilder = statementBuilder;
648    }
649 }
Popular Tags