KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > orm > jdo > JdoTemplate


1 /*
2  * Copyright 2002-2007 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.springframework.orm.jdo;
18
19 import java.lang.reflect.InvocationHandler JavaDoc;
20 import java.lang.reflect.InvocationTargetException JavaDoc;
21 import java.lang.reflect.Method JavaDoc;
22 import java.lang.reflect.Proxy JavaDoc;
23 import java.util.Collection JavaDoc;
24 import java.util.Map JavaDoc;
25
26 import javax.jdo.JDOException;
27 import javax.jdo.PersistenceManager;
28 import javax.jdo.PersistenceManagerFactory;
29 import javax.jdo.Query;
30
31 import org.springframework.dao.DataAccessException;
32 import org.springframework.dao.InvalidDataAccessApiUsageException;
33 import org.springframework.transaction.support.TransactionSynchronizationManager;
34 import org.springframework.util.Assert;
35 import org.springframework.util.ClassUtils;
36 import org.springframework.util.ReflectionUtils;
37
38 /**
39  * Helper class that simplifies JDO data access code, and converts
40  * JDOExceptions into Spring DataAccessExceptions, following the
41  * <code>org.springframework.dao</code> exception hierarchy.
42  *
43  * <p>The central method is <code>execute</code>, supporting JDO access code
44  * implementing the {@link JdoCallback} interface. It provides JDO PersistenceManager
45  * handling such that neither the JdoCallback implementation nor the calling
46  * code needs to explicitly care about retrieving/closing PersistenceManagers,
47  * or handling JDO lifecycle exceptions.
48  *
49  * <p>Typically used to implement data access or business logic services that
50  * use JDO within their implementation but are JDO-agnostic in their interface.
51  * The latter or code calling the latter only have to deal with business
52  * objects, query objects, and <code>org.springframework.dao</code> exceptions.
53  *
54  * <p>Can be used within a service implementation via direct instantiation
55  * with a PersistenceManagerFactory reference, or get prepared in an
56  * application context and given to services as bean reference.
57  * Note: The PersistenceManagerFactory should always be configured as bean in
58  * the application context, in the first case given to the service directly,
59  * in the second case to the prepared template.
60  *
61  * <p>This class can be considered as direct alternative to working with the
62  * raw JDO PersistenceManager API (through
63  * <code>PersistenceManagerFactoryUtils.getPersistenceManager()</code>).
64  * The major advantage is its automatic conversion to DataAccessExceptions, the
65  * major disadvantage that no checked application exceptions can get thrown from
66  * within data access code. Corresponding checks and the actual throwing of such
67  * exceptions can often be deferred to after callback execution, though.
68  *
69  * <p>Note that even if {@link JdoTransactionManager} is used for transaction
70  * demarcation in higher-level services, all those services above the data
71  * access layer don't need to be JDO-aware. Setting such a special
72  * PlatformTransactionManager is a configuration issue, without introducing
73  * code dependencies: For example, switching to JTA is just a matter of
74  * Spring configuration (use JtaTransactionManager instead) and JDO provider
75  * configuration, neither affecting application code.
76  *
77  * <p>{@link LocalPersistenceManagerFactoryBean} is the preferred way of obtaining
78  * a reference to a specific PersistenceManagerFactory, at least in a non-EJB
79  * environment. The Spring application context will manage its lifecycle,
80  * initializing and shutting down the factory as part of the application.
81  *
82  * <p>Note that lazy loading will just work with an open JDO PersistenceManager,
83  * either within a Spring-driven transaction (with JdoTransactionManager or
84  * JtaTransactionManager) or within OpenPersistenceManagerInViewFilter/Interceptor.
85  * Furthermore, some operations just make sense within transactions,
86  * for example: <code>evict</code>, <code>evictAll</code>, <code>flush</code>.
87  *
88  * <p><b>NOTE:</b> This class is compatible with both JDO 1.0 and JDO 2.0,
89  * as far as possible. It uses reflection to adapt to the actual API present
90  * on the class path (concretely: for the <code>newObjectIdInstance</code>,
91  * <code>makePersistent</code> and <code>makePersistentAll</code> methods).
92  * Make sure that the JDO API jar on your class path matches the one that
93  * your JDO provider has been compiled against!
94  *
95  * @author Juergen Hoeller
96  * @since 03.06.2003
97  * @see #setPersistenceManagerFactory
98  * @see JdoCallback
99  * @see javax.jdo.PersistenceManager
100  * @see JdoInterceptor
101  * @see LocalPersistenceManagerFactoryBean
102  * @see org.springframework.jndi.JndiObjectFactoryBean
103  * @see JdoTransactionManager
104  * @see org.springframework.transaction.jta.JtaTransactionManager
105  * @see org.springframework.orm.jdo.support.OpenPersistenceManagerInViewFilter
106  * @see org.springframework.orm.jdo.support.OpenPersistenceManagerInViewInterceptor
107  */

108 public class JdoTemplate extends JdoAccessor implements JdoOperations {
109
110     private static Method JavaDoc newObjectIdInstanceMethod;
111
112     private static Method JavaDoc makePersistentMethod;
113
114     private static Method JavaDoc makePersistentAllMethod;
115
116     static {
117         // Determine whether the JDO 1.0 newObjectIdInstance(Class, String) method
118
// is available, for use in JdoTemplate's getObjectById implementation.
119
try {
120             newObjectIdInstanceMethod = PersistenceManager.class.getMethod(
121                     "newObjectIdInstance", new Class JavaDoc[] {Class JavaDoc.class, String JavaDoc.class});
122         }
123         catch (NoSuchMethodException JavaDoc ex) {
124             newObjectIdInstanceMethod = null;
125         }
126         // Fetch makePersistent(Object) method through reflection
127
// for use in JdoTemplate's makePersistent implementation.
128
// Return value is void in JDO 1.0 but Object in JDO 2.0.
129
try {
130             makePersistentMethod = PersistenceManager.class.getMethod(
131                     "makePersistent", new Class JavaDoc[] {Object JavaDoc.class});
132         }
133         catch (NoSuchMethodException JavaDoc ex) {
134             throw new IllegalStateException JavaDoc("JDO makePersistent(Object) method not available");
135         }
136         // Fetch makePersistent(Object) method through reflection
137
// for use in JdoTemplate's makePersistent implementation.
138
// Return value is void in JDO 1.0 but Collection in JDO 2.0.
139
try {
140             makePersistentAllMethod = PersistenceManager.class.getMethod(
141                     "makePersistentAll", new Class JavaDoc[] {Collection JavaDoc.class});
142         }
143         catch (NoSuchMethodException JavaDoc ex) {
144             throw new IllegalStateException JavaDoc("JDO makePersistentAll(Collection) method not available");
145         }
146     }
147
148
149     private boolean allowCreate = true;
150
151     private boolean exposeNativePersistenceManager = false;
152
153
154     /**
155      * Create a new JdoTemplate instance.
156      */

157     public JdoTemplate() {
158     }
159
160     /**
161      * Create a new JdoTemplate instance.
162      * @param pmf PersistenceManagerFactory to create PersistenceManagers
163      */

164     public JdoTemplate(PersistenceManagerFactory pmf) {
165         setPersistenceManagerFactory(pmf);
166         afterPropertiesSet();
167     }
168
169     /**
170      * Create a new JdoTemplate instance.
171      * @param pmf PersistenceManagerFactory to create PersistenceManagers
172      * @param allowCreate if a non-transactional PersistenceManager should be created
173      * when no transactional PersistenceManager can be found for the current thread
174      */

175     public JdoTemplate(PersistenceManagerFactory pmf, boolean allowCreate) {
176         setPersistenceManagerFactory(pmf);
177         setAllowCreate(allowCreate);
178         afterPropertiesSet();
179     }
180
181     /**
182      * Set if a new PersistenceManager should be created when no transactional
183      * PersistenceManager can be found for the current thread.
184      * <p>JdoTemplate is aware of a corresponding PersistenceManager bound to the
185      * current thread, for example when using JdoTransactionManager.
186      * If allowCreate is true, a new non-transactional PersistenceManager will be
187      * created if none found, which needs to be closed at the end of the operation.
188      * If false, an IllegalStateException will get thrown in this case.
189      * @see PersistenceManagerFactoryUtils#getPersistenceManager(javax.jdo.PersistenceManagerFactory, boolean)
190      */

191     public void setAllowCreate(boolean allowCreate) {
192         this.allowCreate = allowCreate;
193     }
194
195     /**
196      * Return if a new PersistenceManager should be created if no thread-bound found.
197      */

198     public boolean isAllowCreate() {
199         return allowCreate;
200     }
201
202     /**
203      * Set whether to expose the native JDO PersistenceManager to JdoCallback
204      * code. Default is "false": a PersistenceManager proxy will be returned,
205      * suppressing <code>close</code> calls and automatically applying transaction
206      * timeouts (if any).
207      * <p>As there is often a need to cast to a provider-specific PersistenceManager
208      * class in DAOs that use the JDO 1.0 API, for JDO 2.0 previews and other
209      * provider-specific functionality, the exposed proxy implements all interfaces
210      * implemented by the original PersistenceManager. If this is not sufficient,
211      * turn this flag to "true".
212      * @see JdoCallback
213      * @see javax.jdo.PersistenceManager
214      * @see #prepareQuery
215      */

216     public void setExposeNativePersistenceManager(boolean exposeNativePersistenceManager) {
217         this.exposeNativePersistenceManager = exposeNativePersistenceManager;
218     }
219
220     /**
221      * Return whether to expose the native JDO PersistenceManager to JdoCallback
222      * code, or rather a PersistenceManager proxy.
223      */

224     public boolean isExposeNativePersistenceManager() {
225         return exposeNativePersistenceManager;
226     }
227
228
229     public Object JavaDoc execute(JdoCallback action) throws DataAccessException {
230         return execute(action, isExposeNativePersistenceManager());
231     }
232
233     public Collection JavaDoc executeFind(JdoCallback action) throws DataAccessException {
234         Object JavaDoc result = execute(action, isExposeNativePersistenceManager());
235         if (result != null && !(result instanceof Collection JavaDoc)) {
236             throw new InvalidDataAccessApiUsageException(
237                     "Result object returned from JdoCallback isn't a Collection: [" + result + "]");
238         }
239         return (Collection JavaDoc) result;
240     }
241
242     /**
243      * Execute the action specified by the given action object within a
244      * PersistenceManager.
245      * @param action callback object that specifies the JDO action
246      * @param exposeNativePersistenceManager whether to expose the native
247      * JDO persistence manager to callback code
248      * @return a result object returned by the action, or <code>null</code>
249      * @throws org.springframework.dao.DataAccessException in case of JDO errors
250      */

251     public Object JavaDoc execute(JdoCallback action, boolean exposeNativePersistenceManager) throws DataAccessException {
252         Assert.notNull(action, "Callback object must not be null");
253
254         PersistenceManager pm = PersistenceManagerFactoryUtils.getPersistenceManager(
255             getPersistenceManagerFactory(), isAllowCreate());
256         boolean existingTransaction =
257             TransactionSynchronizationManager.hasResource(getPersistenceManagerFactory());
258         try {
259             PersistenceManager pmToExpose = (exposeNativePersistenceManager ? pm : createPersistenceManagerProxy(pm));
260             Object JavaDoc result = action.doInJdo(pmToExpose);
261             flushIfNecessary(pm, existingTransaction);
262             return postProcessResult(result, pm, existingTransaction);
263         }
264         catch (JDOException ex) {
265             throw convertJdoAccessException(ex);
266         }
267         catch (RuntimeException JavaDoc ex) {
268             // callback code threw application exception
269
throw ex;
270         }
271         finally {
272             PersistenceManagerFactoryUtils.releasePersistenceManager(pm, getPersistenceManagerFactory());
273         }
274     }
275
276     /**
277      * Create a close-suppressing proxy for the given JDO PersistenceManager.
278      * Called by the <code>execute</code> method.
279      * <p>The proxy also prepares returned JDO Query objects.
280      * @param pm the JDO PersistenceManager to create a proxy for
281      * @return the PersistenceManager proxy, implementing all interfaces
282      * implemented by the passed-in PersistenceManager object (that is,
283      * also implementing all provider-specific extension interfaces)
284      * @see javax.jdo.PersistenceManager#close()
285      * @see #execute(JdoCallback, boolean)
286      * @see #prepareQuery
287      */

288     protected PersistenceManager createPersistenceManagerProxy(PersistenceManager pm) {
289         Class JavaDoc[] ifcs = ClassUtils.getAllInterfaces(pm);
290         return (PersistenceManager) Proxy.newProxyInstance(
291                 getClass().getClassLoader(), ifcs, new CloseSuppressingInvocationHandler(pm));
292     }
293
294     /**
295      * Post-process the given result object, which might be a Collection.
296      * Called by the <code>execute</code> method.
297      * <p>Default implementation always returns the passed-in Object as-is.
298      * Subclasses might override this to automatically detach result
299      * collections or even single result objects.
300      * @param pm the current JDO PersistenceManager
301      * @param result the result object (might be a Collection)
302      * @param existingTransaction if executing within an existing transaction
303      * (within an existing JDO PersistenceManager that won't be closed immediately)
304      * @return the post-processed result object (can be simply be the passed-in object)
305      * @see #execute(JdoCallback, boolean)
306      */

307     protected Object JavaDoc postProcessResult(Object JavaDoc result, PersistenceManager pm, boolean existingTransaction) {
308         return result;
309     }
310
311
312     //-------------------------------------------------------------------------
313
// Convenience methods for load, save, delete
314
//-------------------------------------------------------------------------
315

316     public Object JavaDoc getObjectById(final Object JavaDoc objectId) throws DataAccessException {
317         return execute(new JdoCallback() {
318             public Object JavaDoc doInJdo(PersistenceManager pm) throws JDOException {
319                 return pm.getObjectById(objectId, true);
320             }
321         }, true);
322     }
323
324     public Object JavaDoc getObjectById(final Class JavaDoc entityClass, final Object JavaDoc idValue) throws DataAccessException {
325         return execute(new JdoCallback() {
326             public Object JavaDoc doInJdo(PersistenceManager pm) throws JDOException {
327                 // Use JDO 1.0 newObjectIdInstance(Class, String) method, if available.
328
if (newObjectIdInstanceMethod != null) {
329                     Object JavaDoc id = ReflectionUtils.invokeMethod(
330                             newObjectIdInstanceMethod, pm, new Object JavaDoc[] {entityClass, idValue.toString()});
331                     return pm.getObjectById(id, true);
332                 }
333                 // Use JDO 2.0 getObjectById(Class, Object) method.
334
return pm.getObjectById(entityClass, idValue);
335             }
336         }, true);
337     }
338
339     public void evict(final Object JavaDoc entity) throws DataAccessException {
340         execute(new JdoCallback() {
341             public Object JavaDoc doInJdo(PersistenceManager pm) throws JDOException {
342                 pm.evict(entity);
343                 return null;
344             }
345         }, true);
346     }
347
348     public void evictAll(final Collection JavaDoc entities) throws DataAccessException {
349         execute(new JdoCallback() {
350             public Object JavaDoc doInJdo(PersistenceManager pm) throws JDOException {
351                 pm.evictAll(entities);
352                 return null;
353             }
354         }, true);
355     }
356
357     public void evictAll() throws DataAccessException {
358         execute(new JdoCallback() {
359             public Object JavaDoc doInJdo(PersistenceManager pm) throws JDOException {
360                 pm.evictAll();
361                 return null;
362             }
363         }, true);
364     }
365
366     public void refresh(final Object JavaDoc entity) throws DataAccessException {
367         execute(new JdoCallback() {
368             public Object JavaDoc doInJdo(PersistenceManager pm) throws JDOException {
369                 pm.refresh(entity);
370                 return null;
371             }
372         }, true);
373     }
374
375     public void refreshAll(final Collection JavaDoc entities) throws DataAccessException {
376         execute(new JdoCallback() {
377             public Object JavaDoc doInJdo(PersistenceManager pm) throws JDOException {
378                 pm.refreshAll(entities);
379                 return null;
380             }
381         }, true);
382     }
383
384     public void refreshAll() throws DataAccessException {
385         execute(new JdoCallback() {
386             public Object JavaDoc doInJdo(PersistenceManager pm) throws JDOException {
387                 pm.refreshAll();
388                 return null;
389             }
390         }, true);
391     }
392
393     public void makePersistent(final Object JavaDoc entity) throws DataAccessException {
394         execute(new JdoCallback() {
395             public Object JavaDoc doInJdo(PersistenceManager pm) throws JDOException {
396                 return ReflectionUtils.invokeMethod(makePersistentMethod, pm, new Object JavaDoc[] {entity});
397             }
398         }, true);
399     }
400
401     public void makePersistentAll(final Collection JavaDoc entities) throws DataAccessException {
402         execute(new JdoCallback() {
403             public Object JavaDoc doInJdo(PersistenceManager pm) throws JDOException {
404                 return ReflectionUtils.invokeMethod(makePersistentAllMethod, pm, new Object JavaDoc[] {entities});
405             }
406         }, true);
407     }
408
409     public void deletePersistent(final Object JavaDoc entity) throws DataAccessException {
410         execute(new JdoCallback() {
411             public Object JavaDoc doInJdo(PersistenceManager pm) throws JDOException {
412                 pm.deletePersistent(entity);
413                 return null;
414             }
415         }, true);
416     }
417
418     public void deletePersistentAll(final Collection JavaDoc entities) throws DataAccessException {
419         execute(new JdoCallback() {
420             public Object JavaDoc doInJdo(PersistenceManager pm) throws JDOException {
421                 pm.deletePersistentAll(entities);
422                 return null;
423             }
424         }, true);
425     }
426
427     public Object JavaDoc detachCopy(final Object JavaDoc entity) {
428         return execute(new JdoCallback() {
429             public Object JavaDoc doInJdo(PersistenceManager pm) throws JDOException {
430                 return getJdoDialect().detachCopy(pm, entity);
431             }
432         }, true);
433     }
434
435     public Collection JavaDoc detachCopyAll(final Collection JavaDoc entities) {
436         return (Collection JavaDoc) execute(new JdoCallback() {
437             public Object JavaDoc doInJdo(PersistenceManager pm) throws JDOException {
438                 return getJdoDialect().detachCopyAll(pm, entities);
439             }
440         }, true);
441     }
442
443     public Object JavaDoc attachCopy(final Object JavaDoc detachedEntity) {
444         return execute(new JdoCallback() {
445             public Object JavaDoc doInJdo(PersistenceManager pm) throws JDOException {
446                 return getJdoDialect().attachCopy(pm, detachedEntity);
447             }
448         }, true);
449     }
450
451     public Collection JavaDoc attachCopyAll(final Collection JavaDoc detachedEntities) {
452         return (Collection JavaDoc) execute(new JdoCallback() {
453             public Object JavaDoc doInJdo(PersistenceManager pm) throws JDOException {
454                 return getJdoDialect().attachCopyAll(pm, detachedEntities);
455             }
456         }, true);
457     }
458
459     public void flush() throws DataAccessException {
460         execute(new JdoCallback() {
461             public Object JavaDoc doInJdo(PersistenceManager pm) throws JDOException {
462                 getJdoDialect().flush(pm);
463                 return null;
464             }
465         }, true);
466     }
467
468
469     //-------------------------------------------------------------------------
470
// Convenience finder methods
471
//-------------------------------------------------------------------------
472

473     public Collection JavaDoc find(Class JavaDoc entityClass) throws DataAccessException {
474         return find(entityClass, null, null);
475     }
476
477     public Collection JavaDoc find(Class JavaDoc entityClass, String JavaDoc filter) throws DataAccessException {
478         return find(entityClass, filter, null);
479     }
480
481     public Collection JavaDoc find(final Class JavaDoc entityClass, final String JavaDoc filter, final String JavaDoc ordering)
482             throws DataAccessException {
483
484         return (Collection JavaDoc) execute(new JdoCallback() {
485             public Object JavaDoc doInJdo(PersistenceManager pm) throws JDOException {
486                 Query query = (filter != null ? pm.newQuery(entityClass, filter) : pm.newQuery(entityClass));
487                 prepareQuery(query);
488                 if (ordering != null) {
489                     query.setOrdering(ordering);
490                 }
491                 return query.execute();
492             }
493         }, true);
494     }
495
496     public Collection JavaDoc find(Class JavaDoc entityClass, String JavaDoc filter, String JavaDoc parameters, Object JavaDoc[] values)
497             throws DataAccessException {
498
499         return find(entityClass, filter, parameters, values, null);
500     }
501
502     public Collection JavaDoc find(
503             final Class JavaDoc entityClass, final String JavaDoc filter, final String JavaDoc parameters, final Object JavaDoc[] values,
504             final String JavaDoc ordering) throws DataAccessException {
505
506         return (Collection JavaDoc) execute(new JdoCallback() {
507             public Object JavaDoc doInJdo(PersistenceManager pm) throws JDOException {
508                 Query query = pm.newQuery(entityClass, filter);
509                 prepareQuery(query);
510                 query.declareParameters(parameters);
511                 if (ordering != null) {
512                     query.setOrdering(ordering);
513                 }
514                 return query.executeWithArray(values);
515             }
516         }, true);
517     }
518
519     public Collection JavaDoc find(Class JavaDoc entityClass, String JavaDoc filter, String JavaDoc parameters, Map JavaDoc values)
520             throws DataAccessException {
521
522         return find(entityClass, filter, parameters, values, null);
523     }
524
525     public Collection JavaDoc find(
526             final Class JavaDoc entityClass, final String JavaDoc filter, final String JavaDoc parameters, final Map JavaDoc values,
527             final String JavaDoc ordering) throws DataAccessException {
528
529         return (Collection JavaDoc) execute(new JdoCallback() {
530             public Object JavaDoc doInJdo(PersistenceManager pm) throws JDOException {
531                 Query query = pm.newQuery(entityClass, filter);
532                 prepareQuery(query);
533                 query.declareParameters(parameters);
534                 if (ordering != null) {
535                     query.setOrdering(ordering);
536                 }
537                 return query.executeWithMap(values);
538             }
539         }, true);
540     }
541
542     public Collection JavaDoc find(final String JavaDoc language, final Object JavaDoc queryObject) throws DataAccessException {
543         return (Collection JavaDoc) execute(new JdoCallback() {
544             public Object JavaDoc doInJdo(PersistenceManager pm) throws JDOException {
545                 Query query = pm.newQuery(language, queryObject);
546                 prepareQuery(query);
547                 return query.execute();
548             }
549         }, true);
550     }
551
552     public Collection JavaDoc find(final String JavaDoc queryString) throws DataAccessException {
553         return (Collection JavaDoc) execute(new JdoCallback() {
554             public Object JavaDoc doInJdo(PersistenceManager pm) throws JDOException {
555                 Query query = pm.newQuery(queryString);
556                 prepareQuery(query);
557                 return query.execute();
558             }
559         }, true);
560     }
561
562     public Collection JavaDoc find(final String JavaDoc queryString, final Object JavaDoc[] values) throws DataAccessException {
563         return (Collection JavaDoc) execute(new JdoCallback() {
564             public Object JavaDoc doInJdo(PersistenceManager pm) throws JDOException {
565                 Query query = pm.newQuery(queryString);
566                 prepareQuery(query);
567                 return query.executeWithArray(values);
568             }
569         }, true);
570     }
571
572     public Collection JavaDoc find(final String JavaDoc queryString, final Map JavaDoc values) throws DataAccessException {
573         return (Collection JavaDoc) execute(new JdoCallback() {
574             public Object JavaDoc doInJdo(PersistenceManager pm) throws JDOException {
575                 Query query = pm.newQuery(queryString);
576                 prepareQuery(query);
577                 return query.executeWithMap(values);
578             }
579         }, true);
580     }
581
582     public Collection JavaDoc findByNamedQuery(final Class JavaDoc entityClass, final String JavaDoc queryName) throws DataAccessException {
583         return (Collection JavaDoc) execute(new JdoCallback() {
584             public Object JavaDoc doInJdo(PersistenceManager pm) throws JDOException {
585                 Query query = getJdoDialect().newNamedQuery(pm, entityClass, queryName);
586                 prepareQuery(query);
587                 return query.execute();
588             }
589         }, true);
590     }
591
592     public Collection JavaDoc findByNamedQuery(final Class JavaDoc entityClass, final String JavaDoc queryName, final Object JavaDoc[] values)
593             throws DataAccessException {
594
595         return (Collection JavaDoc) execute(new JdoCallback() {
596             public Object JavaDoc doInJdo(PersistenceManager pm) throws JDOException {
597                 Query query = getJdoDialect().newNamedQuery(pm, entityClass, queryName);
598                 prepareQuery(query);
599                 return query.executeWithArray(values);
600             }
601         }, true);
602     }
603
604     public Collection JavaDoc findByNamedQuery(final Class JavaDoc entityClass, final String JavaDoc queryName, final Map JavaDoc values)
605             throws DataAccessException {
606
607         return (Collection JavaDoc) execute(new JdoCallback() {
608             public Object JavaDoc doInJdo(PersistenceManager pm) throws JDOException {
609                 Query query = getJdoDialect().newNamedQuery(pm, entityClass, queryName);
610                 prepareQuery(query);
611                 return query.executeWithMap(values);
612             }
613         }, true);
614     }
615
616
617     /**
618      * Prepare the given JDO query object. To be used within a JdoCallback.
619      * Applies a transaction timeout, if any. If you don't use such timeouts,
620      * the call is a no-op.
621      * <p>In general, prefer a proxied PersistenceManager instead, which will
622      * automatically apply the transaction timeout (through the use of a special
623      * PersistenceManager proxy). You need to set the "exposeNativePersistenceManager"
624      * property to "false" to activate this. Note that you won't be able to cast
625      * to a provider-specific JDO PersistenceManager class anymore then.
626      * @param query the JDO query object
627      * @throws JDOException if the query could not be properly prepared
628      * @see JdoCallback#doInJdo
629      * @see PersistenceManagerFactoryUtils#applyTransactionTimeout
630      * @see #setExposeNativePersistenceManager
631      */

632     public void prepareQuery(Query query) throws JDOException {
633         PersistenceManagerFactoryUtils.applyTransactionTimeout(
634                 query, getPersistenceManagerFactory(), getJdoDialect());
635     }
636
637
638     /**
639      * Invocation handler that suppresses close calls on JDO PersistenceManagers.
640      * Also prepares returned Query objects.
641      * @see javax.jdo.PersistenceManager#close()
642      */

643     private class CloseSuppressingInvocationHandler implements InvocationHandler JavaDoc {
644
645         private final PersistenceManager target;
646
647         public CloseSuppressingInvocationHandler(PersistenceManager target) {
648             this.target = target;
649         }
650
651         public Object JavaDoc invoke(Object JavaDoc proxy, Method JavaDoc method, Object JavaDoc[] args) throws Throwable JavaDoc {
652             // Invocation on PersistenceManager interface (or provider-specific extension) coming in...
653

654             if (method.getName().equals("equals")) {
655                 // Only consider equal when proxies are identical.
656
return (proxy == args[0] ? Boolean.TRUE : Boolean.FALSE);
657             }
658             else if (method.getName().equals("hashCode")) {
659                 // Use hashCode of PersistenceManager proxy.
660
return new Integer JavaDoc(hashCode());
661             }
662             else if (method.getName().equals("close")) {
663                 // Handle close method: suppress, not valid.
664
return null;
665             }
666
667             // Invoke method on target PersistenceManager.
668
try {
669                 Object JavaDoc retVal = method.invoke(this.target, args);
670
671                 // If return value is a JDO Query object, apply transaction timeout.
672
if (retVal instanceof Query) {
673                     prepareQuery(((Query) retVal));
674                 }
675
676                 return retVal;
677             }
678             catch (InvocationTargetException JavaDoc ex) {
679                 throw ex.getTargetException();
680             }
681         }
682     }
683
684 }
685
Popular Tags