1 /**
2 * Copyright 2005-2008 the original author or authors.
3 *
4 * Licensed under the Gnu General Pubic License, Version 2.0 (the
5 * "License"); you may not use this file except in compliance with
6 * the License. You may obtain a copy of the License at
7 *
8 * http://www.opensource.org/licenses/gpl-license.php
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 * See the Gnu General Public License for more details.
14 */
15 package org.figure8.join.core.persistence;
16
17 import org.figure8.join.util.LogUtil;
18 import org.figure8.join.core.EntityObject;
19 import org.figure8.join.core.InfrastructureException;
20
21 import org.apache.commons.logging.Log;
22 import org.springframework.orm.hibernate.HibernateCallback;
23 import org.springframework.orm.hibernate.SessionFactoryUtils;
24 import org.springframework.orm.hibernate.support.HibernateDaoSupport;
25 import net.sf.hibernate.Query;
26 import net.sf.hibernate.Session;
27 import net.sf.hibernate.LockMode;
28 import net.sf.hibernate.Hibernate;
29 import net.sf.hibernate.ReplicationMode;
30 import net.sf.hibernate.HibernateException;
31
32 import java.util.List;
33 import java.util.Collections;
34 import java.util.HashSet;
35 /**
36 * This is a base class for Dao implementations using Hibernate as their
37 * ORM solution. This base class also extends Spring container Hibernate
38 * support class in order to use Spring's features such as declarative transaction
39 * demarcation ...
40 * @author <a href="mailto:laurent.broudoux@free.fr">Laurent Broudoux</a>
41 * @version $Revision: 1.3 $
42 */
43 public abstract class HibernateObjectDao extends HibernateDaoSupport
44 implements ObjectDao{
45
46
47
48 /** Logger */
49 protected Log log;
50
51
52
53
54 /** Default constructor. */
55 public HibernateObjectDao(){
56 log = LogUtil.getLog(this.getPersistentClass());
57 }
58
59
60
61
62 /**
63 * Save the given entity into underlying datastore.
64 * @param entityobject EntityObject to save
65 */
66 public void save(EntityObject entityobject){
67 try{
68
69
70
71
72
73 getHibernateTemplate().saveOrUpdateCopy(entityobject);
74 }
75 catch (Exception e){
76 log.error("Exception in saveOrUpdate()!", e);
77 throw new InfrastructureException(e);
78 }
79 }
80
81 /**
82 * Remove the given entity object from underlying datastore.
83 * @param entityobject EntityObject to remove
84 */
85 public void remove(EntityObject entityobject){
86 try{
87
88 getHibernateTemplate().delete(entityobject);
89 }
90 catch (Exception e){
91 log.error("Exception in remove()!", e);
92 throw new InfrastructureException(e);
93 }
94 }
95
96 /**
97 * Re-read the content of the given entity from underlying datastore.
98 * @param entityobject EntityObject to refresh content
99 */
100 public void refresh(EntityObject entityobject){
101 try{
102
103 getHibernateTemplate().refresh(entityobject);
104 }
105 catch (Exception e){
106 log.error("Exception in refresh()!", e);
107 throw new InfrastructureException(e);
108 }
109 }
110
111 /**
112 * Force initialization of the given entity from underlying datastore
113 * (this may involves initialization of lazily loaded relations fields)
114 * @param entityobject EntityObject to initialize
115 */
116 public void initialize(EntityObject entityobject){
117 try{
118
119 getHibernateTemplate().lock(entityobject, LockMode.READ);
120 getHibernateTemplate().initialize(entityobject);
121 }
122 catch (Exception e){
123 log.error("Exception in initialize()!", e);
124 throw new InfrastructureException(e);
125 }
126 }
127
128 /**
129 * Force initialization of the given entity association from underlying datastore
130 * @param entityobject EntityObject whose association shoud be initialized
131 * @param proxy A proxy object representing entoty association (this may be a collection)
132 */
133 public void initializeAssociation(EntityObject entityobject, Object proxy){
134 try{
135
136 getHibernateTemplate().lock(entityobject, LockMode.READ);
137 getHibernateTemplate().initialize(proxy);
138 }
139 catch (Exception e){
140 log.error("Exception in initializeAssociation()!", e);
141 throw new InfrastructureException(e);
142 }
143 }
144
145 /**
146 * Check if an object (EntityObject or association proxy) is initialized from datastore
147 * @param object The object to check initialization for
148 * @return true if object has been loaded from datastore, false otherwise
149 */
150 public boolean isInitialized(Object object){
151 try{
152 return Hibernate.isInitialized(object);
153 }
154 catch (Exception e){
155 log.error("Exception in isInitialized()!", e);
156 throw new InfrastructureException(e);
157 }
158 }
159
160 /**
161 * Persist the object state throughout the cluster.
162 * @param obj The object to replicate
163 */
164 public void replicate(final Object obj){
165 try{
166
167 getHibernateTemplate().execute(new HibernateCallback(){
168 public Object doInHibernate(Session session) throws HibernateException{
169 session.replicate(obj, ReplicationMode.OVERWRITE);
170 return null;
171 }
172 });
173 }
174 catch(Exception e){
175 log.error("Exception in replicate()!", e);
176 throw new InfrastructureException(e);
177 }
178 }
179
180 /**
181 * Find all entity objects associated with this Dao.
182 * @return A List of EntityObjects
183 */
184 public List findAll(){
185 return findAllSorted(null);
186 }
187
188 /**
189 * Find all entity objects asscoiated with this Dao.
190 * The result list is sorted by <b>sortField</b> criteria.
191 * @param sortField Field for sorting criteria
192 * @return A List of EntityObjects
193 */
194 public List findAllSorted(String sortField){
195
196 String query = "FROM " + getPersistentClass().getName() + " result";
197 if (sortField != null)
198 query = query + " ORDER BY LOWER(result." + sortField + ")";
199 try{
200
201 List result = getHibernateTemplate().find(query);
202 if (result == null)
203 return Collections.EMPTY_LIST;
204 return result;
205 }
206 catch (Exception e){
207 log.error("Exception in findAllSorted()!", e);
208 throw new InfrastructureException(e);
209 }
210 }
211
212
213
214
215 /**
216 * Retrieve an object of the persistent class using its unique identifier (primary key)
217 * @param id The identifier of the persistent object to retrieve
218 * @return The EntityObject corresponding to <b>id</b>
219 */
220 protected EntityObject getById(final long id){
221 try{
222
223 EntityObject obj = (EntityObject)getHibernateTemplate().execute(new HibernateCallback(){
224 public Object doInHibernate(Session session) throws HibernateException{
225 return session.get(getPersistentClass(), new Long(id));
226 }
227 });
228 return obj;
229 }
230 catch (Exception e){
231 log.error("Exception in getById()!", e);
232 throw new InfrastructureException(e);
233 }
234 }
235
236 /**
237 * Execute a named query defined in a Hibernate mapping file.
238 * Query will not be cached.
239 * @param queryName Name of the query to execute
240 * @return List of entity objects
241 */
242 protected List findNamedQuery(String queryName){
243 return findNamedQuery(queryName, false);
244 }
245
246 /**
247 * Execute a named query defined in a Hibernate mapping file.
248 * @param queryName Name of the query to execute
249 * @param cacheable wether the query is cached or not
250 * @return List of entity objects
251 */
252 protected List findNamedQuery(String queryName, boolean cacheable){
253 return findNamedQueryStringParam(queryName, null, null, cacheable);
254 }
255
256 /**
257 * Execute a named query defined in a Hibernate mapping file.
258 * @param queryName Name of the query to execute
259 * @param cacheable wether the query is cached or not
260 * @param maxResultCount Max number of results
261 * @return List of entity objects
262 */
263 protected List findNamedQuery(String queryName, boolean cacheable, int maxResultCount){
264 return findNamedQueryStringParam(queryName, null, null, cacheable, maxResultCount);
265 }
266
267 /**
268 * Execute a named query with one param defined in a Hibernate mapping file.
269 * Query will not be cached.
270 * @param queryName Name of the query to execute
271 * @param paramName Name of the query parameter
272 * @param paramValue Value of the query parameter
273 * @return List of entity objects
274 */
275 protected List findNamedQueryStringParam(String queryName, String paramName, Object paramValue){
276 return findNamedQueryStringParam(queryName, paramName, paramValue, false);
277 }
278
279 /**
280 * Execute a named query with one param defined in a Hibernate mapping file.
281 * @param queryName Name of the query to execute
282 * @param paramName Name of the query parameter
283 * @param paramValue Value of the query parameter
284 * @param cacheable wether the query is cached or not
285 * @return List of entity objects
286 */
287 protected List findNamedQueryStringParam(String queryName, String paramName, Object paramValue, boolean cacheable){
288 return findNamedQueryStringParams(queryName, paramName, paramValue, null, null, cacheable);
289 }
290
291 /**
292 * Execute a named query with one param defined in a Hibernate mapping file.
293 * @param queryName Name of the query to execute
294 * @param paramName Name of the query parameter
295 * @param paramValue Value of the query parameter
296 * @param cacheable wether the query is cached or not
297 * @param maxResultCount Max number of results
298 * @return List of entity objects
299 */
300 protected List findNamedQueryStringParam(String queryName, String paramName, Object paramValue, boolean cacheable, int maxResultCount){
301 return findNamedQueryStringParams(queryName, paramName, paramValue, null, null, null, null, cacheable, maxResultCount);
302 }
303
304 /**
305 * Execute a named query with two params defined in a Hibernate mapping file.
306 * Query will not be cached.
307 * @param queryName Name of the query to execute
308 * @param paramName Name of the query parameter
309 * @param paramValue Value of the query parameter
310 * @param param2Name Name of the 2nd query parameter
311 * @param param2Value Value of the 2nd query parameter
312 * @return List of entity objects
313 */
314 protected List findNamedQueryStringParams(String queryName, String paramName, Object paramValue, String param2Name, Object param2Value){
315 return findNamedQueryStringParams(queryName, paramName, paramValue, param2Name, param2Value, null, null, false);
316 }
317
318 /**
319 * Execute a named query with two params defined in a Hibernate mapping file.
320 * @param queryName Name of the query to execute
321 * @param paramName Name of the query parameter
322 * @param paramValue Value of the query parameter
323 * @param param2Name Name of the 2nd query parameter
324 * @param param2Value Value of the 2nd query parameter
325 * @param cacheable wether the query is cached or not
326 * @return List of entity objects
327 */
328 protected List findNamedQueryStringParams(String queryName, String paramName, Object paramValue, String param2Name, Object param2Value, boolean cacheable){
329 return findNamedQueryStringParams(queryName, paramName, paramValue, param2Name, param2Value, null, null, cacheable, -1);
330 }
331
332 /**
333 * Execute a named query with three params defined in a Hibernate mapping file.
334 * Query will not be cached.
335 * @param queryName Name of the query to execute
336 * @param paramName Name of the query parameter
337 * @param paramValue Value of the query parameter
338 * @param param2Name Name of the 2nd query parameter
339 * @param param2Value Value of the 2nd query parameter
340 * @param param3Name Name of the 3rd query parameter
341 * @param param3Value Value of the 3rd query parameter
342 * @return List of entity objects
343 */
344 protected List findNamedQueryStringParams(String queryName, String paramName, Object paramValue,
345 String param2Name, Object param2Value, String param3Name, Object param3Value){
346 return findNamedQueryStringParams(queryName, paramName, paramValue, param2Name, param2Value, param3Name, param3Value, false);
347 }
348
349 /**
350 * Execute a named query with two params defined in a Hibernate mapping file.
351 * @param queryName Name of the query to execute
352 * @param paramName Name of the query parameter
353 * @param paramValue Value of the query parameter
354 * @param param2Name Name of the 2nd query parameter
355 * @param param2Value Value of the 2nd query parameter
356 * @param param3Name Name of the 3rd query parameter
357 * @param param3Value Value of the 3rd query parameter
358 * @param cacheable wether the query is cached or not
359 * @return List of entity objects
360 */
361 protected List findNamedQueryStringParams(String queryName, String paramName, Object paramValue,
362 String param2Name, Object param2Value, String param3Name, Object param3Value, boolean cacheable){
363 return findNamedQueryStringParams(queryName, paramName, paramValue, param2Name, param2Value, param3Name, param3Value, cacheable, -1);
364 }
365
366
367 /**
368 * Execute a named query with two params defined in a Hibernate mapping file.
369 * @param queryName Name of the query to execute
370 * @param paramName Name of the query parameter
371 * @param paramValue Value of the query parameter
372 * @param param2Name Name of the 2nd query parameter
373 * @param param2Value Value of the 2nd query parameter
374 * @param param3Name Name of the 3rd query parameter
375 * @param param3Value Value of the 3rd query parameter
376 * @param cacheable wether the query is cached or not
377 * @param maxResultCount Max number of results
378 * @return List of entity objects
379 */
380 protected List findNamedQueryStringParams(final String queryName, final String paramName, final Object paramValue,
381 final String param2Name, final Object param2Value, final String param3Name, final Object param3Value, final boolean cacheable, final int maxResultCount){
382
383 return getHibernateTemplate().executeFind(new HibernateCallback(){
384 public Object doInHibernate(Session session) throws HibernateException{
385 Query queryObject = session.getNamedQuery(queryName);
386 if (cacheable)
387 queryObject.setCacheable(true);
388 SessionFactoryUtils.applyTransactionTimeout(queryObject, getSessionFactory());
389 if (paramName != null)
390 queryObject.setParameter(paramName, paramValue);
391 if (param2Name != null)
392 queryObject.setParameter(param2Name, param2Value);
393 if (param3Name != null)
394 queryObject.setParameter(param3Name, param3Value);
395 if (maxResultCount != -1)
396 queryObject.setMaxResults(maxResultCount);
397 return queryObject.list();
398 }
399 });
400 }
401
402 /**
403 * Filter a list of results that should only contain one element
404 * @param results The list of results to filter
405 * @return The element if it is the only one, otherwise log an error and return null
406 */
407 protected Object findSingleObject(List results){
408 if (results != null && results.size() == 1)
409 return results.get(0);
410 if (results != null && results.size() > 1){
411
412
413 HashSet distinctResults = new HashSet(results);
414 if (distinctResults.size() == 1)
415 return distinctResults.iterator().next();
416
417 log.error("Uh oh, problem... - found more than one object when single object requested: " + results);
418 }
419 return null;
420 }
421 }