1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package com.geekologue.md4j.dao.hibernate;
20
21 import java.util.List;
22 import java.util.Map;
23 import java.util.Set;
24
25 import com.geekologue.md4j.dao.DataAccessException;
26 import com.geekologue.md4j.dao.Page;
27 import com.geekologue.md4j.util.Md4jException;
28 import org.hibernate.Criteria;
29 import org.hibernate.HibernateException;
30 import org.hibernate.Query;
31 import org.hibernate.Session;
32 import org.hibernate.criterion.CriteriaSpecification;
33 import org.hibernate.criterion.Projections;
34
35 /***
36 * <p>
37 * Hibernate-based implementation of the Page interface. Used by Hibernate-based DAOs to
38 * page Hibernate Queries, Criteria Queries as well as POJO collection references.
39 * </p>
40 * <p>
41 * Paging a query is as simple as:
42 * </p>
43 * <blockquote>
44 *
45 * <pre>
46 * Page page = new HbmQueryResultPage(session, session
47 * .createQuery("from Type obj order by obj.prop desc"),
48 * pageNumber, maxResults);
49 * </pre>
50 *
51 * </blockquote>
52 * <p>
53 * Which will only load maxResults+1 objects from the database. You can also
54 * page a collection like:
55 * </p>
56 * <blockquote>
57 *
58 * <pre>
59 * Page page = new HbmQueryResultPage(session, object.getChildren(), pageNumber,
60 * maxResults);
61 * </pre>
62 *
63 * </blockquote>
64 *
65 * @author Manos Batsis 7 Sep 2004
66 * @version $Revision$
67 */
68 public class HbmQueryResultPage implements Page {
69 /***
70 *
71 */
72 private static final long serialVersionUID = 1L;
73
74
75
76 private List list = null;
77
78 private Map parentOptions = null;
79
80 private int pageNumber = -1;
81
82 private int pageSize = -1;
83
84 private int totalResultCount = -1;
85
86 private int totalPageCount = -1;
87
88 private boolean first;
89
90 private boolean last;
91
92 private int firstResultIndex;
93
94 private int lastResultIndex;
95
96 private int previous;
97
98 private int next;
99
100 /***
101 * Constructor that will page a query without loading all results
102 *
103 * @param session
104 * The hibernate session that created the query
105 * @param query
106 * The query with any (named or positional) parameters already
107 * set
108 * @param number
109 * The page number (1,2,3...n)
110 * @param size
111 * The number of entries a page should contain
112 */
113 public HbmQueryResultPage(Query query, int number,
114 int size) {
115 try {
116
117
118 this.totalResultCount = query.list().size();
119 this.firstResultIndex = (number - 1) * size;
120 query.setFirstResult(this.firstResultIndex);
121
122
123 query.setMaxResults(size + 1);
124 this.list = query.list();
125 this.pageNumber = number;
126 this.totalPageCount = (int) Math.ceil((float) this.totalResultCount
127 / (float) size);
128 this.first = this.pageNumber == 1;
129 this.last = this.list.size() <= size;
130
131
132
133 if (this.list.size() > size) {
134 this.list.remove(this.list.size() - 1);
135 }
136 } catch (Md4jException e) {
137 throw e;
138 } catch (Exception e) {
139 throw new DataAccessException(e);
140 }
141 }
142
143 /***
144 * Constructor that will page a criteria query without loading all results
145 *
146 * @param session
147 * The hibernate session that created the query
148 * @param query
149 * The criteria query
150 * @param number
151 * The page number (1,2,3...n)
152 * @param size
153 * The number of entries a page should contain
154 */
155 public HbmQueryResultPage(Criteria query,
156 Set projectionProps, int number, int size) {
157 try {
158 this.pageSize = size;
159 this.pageNumber = number;
160
161 this.firstResultIndex = (number - 1) * size;
162
163 this.totalResultCount = ((Integer) query.setProjection(
164 Projections.rowCount()).uniqueResult()).intValue();
165 this.totalPageCount = (int) Math.ceil((float) this.totalResultCount
166 / (float) size);
167 this.first = this.pageNumber == 1;
168 this.last = this.pageNumber == this.totalPageCount;
169 query.setFirstResult(this.firstResultIndex);
170 query.setMaxResults(size);
171
172
173 if (projectionProps != null) {
174 this.list = Helper.getQueryResultAsMapList(query,
175 projectionProps);
176 } else {
177 query.setProjection(null).setResultTransformer(
178 CriteriaSpecification.ROOT_ENTITY);
179 this.list = query.list();
180 }
181 } catch (Md4jException e) {
182 throw e;
183 } catch (Exception e) {
184 throw new DataAccessException(e);
185 }
186 }
187
188 /***
189 * Constructor that will page a collection. Lazy collections are not initialized.
190 * <b>Untested.</b>
191 *
192 * @param session
193 * The Hibernate Session to use
194 * @param collection
195 * The collection to page, e.g.: foo.getBars();
196 * @param pageNumber
197 * The page number (1,2,3...n)
198 * @param pageSize
199 * The number of entries a page should contain
200 *
201 * @throws HibernateException
202 */
203 public HbmQueryResultPage(Session session, Set collection, int number,
204 int size) {
205 this(session.createFilter(collection, ""), number,
206 size);
207 }
208
209 /***
210 * @return Returns the total number of results the query can return, of
211 * which this page instance contains a subset.
212 */
213 public int getTotalResultCount() {
214 return this.totalResultCount;
215 }
216
217 /***
218 * Get the total number of pages that can be used to divide the total
219 * results using the current page size.
220 *
221 * @return the total number of pages
222 */
223 public int getTotalPageCount() {
224 return this.totalPageCount;
225 }
226
227 /***
228 * See if this page is the first
229 *
230 * @return true if first, false otherwise
231 */
232 public boolean isFirst() {
233 return this.first;
234 }
235
236 /***
237 * See if this page is the last
238 *
239 * @return true if last, false otherwise
240 */
241 public boolean isLast() {
242 return this.last;
243 }
244
245 /***
246 * Get the page of results as the list
247 *
248 * @return the list containing the results for this page
249 */
250 public List getList() {
251 return this.list;
252 }
253
254 /***
255 * Get the page number
256 *
257 * @return the page number as given to the constructor
258 */
259 public int getPageNumber() {
260 return this.pageNumber;
261 }
262
263 /*** Get the index of the first result in the page */
264 public int getFirstResultIndex() {
265 return this.firstResultIndex;
266 }
267
268 /***
269 * return pageSize The page size
270 *
271 * @return the page size
272 */
273 public final int getPageSize() {
274 return this.pageSize;
275 }
276
277 /***
278 * @return Returns the last result index
279 */
280 public final int getLastResultIndex() {
281 return this.lastResultIndex;
282 }
283
284 /***
285 * @return Returns the number of the next page
286 */
287 public final int getNext() {
288 return this.next;
289 }
290
291 /***
292 * @return Returns the number of the previous page
293 */
294 public final int getPrevious() {
295 return this.previous;
296 }
297
298 /***
299 *
300 */
301 public void setList(List newList) {
302 this.list = newList;
303 }
304
305 /***
306 * @see com.geekologue.md4j.dao.Page#getParentOptions()
307 */
308 public Map getParentOptions() {
309 return this.parentOptions;
310 }
311
312 /***
313 */
314 public void setParentOptions(Map opts) {
315 this.parentOptions = opts;
316 }
317 }