KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > orm > hibernate3 > HibernateTemplate


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.hibernate3;
18
19 import java.io.Serializable JavaDoc;
20 import java.lang.reflect.InvocationHandler JavaDoc;
21 import java.lang.reflect.InvocationTargetException JavaDoc;
22 import java.lang.reflect.Method JavaDoc;
23 import java.lang.reflect.Proxy JavaDoc;
24 import java.sql.SQLException JavaDoc;
25 import java.util.Collection JavaDoc;
26 import java.util.Iterator JavaDoc;
27 import java.util.List JavaDoc;
28
29 import org.hibernate.Criteria;
30 import org.hibernate.Filter;
31 import org.hibernate.FlushMode;
32 import org.hibernate.Hibernate;
33 import org.hibernate.HibernateException;
34 import org.hibernate.LockMode;
35 import org.hibernate.Query;
36 import org.hibernate.ReplicationMode;
37 import org.hibernate.Session;
38 import org.hibernate.SessionFactory;
39 import org.hibernate.criterion.DetachedCriteria;
40 import org.hibernate.criterion.Example;
41 import org.hibernate.engine.SessionImplementor;
42
43 import org.springframework.dao.DataAccessException;
44 import org.springframework.dao.InvalidDataAccessApiUsageException;
45 import org.springframework.util.Assert;
46
47 /**
48  * Helper class that simplifies Hibernate data access code. Automatically
49  * converts HibernateExceptions into DataAccessExceptions, following the
50  * <code>org.springframework.dao</code> exception hierarchy.
51  *
52  * <p><b>NOTE: As of Hibernate 3.0.1, transactional Hibernate access code can
53  * also be coded in plain Hibernate style. Hence, for newly started projects,
54  * consider adopting the standard Hibernate3 style of coding data access objects
55  * instead, based on <code>SessionFactory.getCurrentSession()</code>.</b>
56  * (Spring's LocalSessionFactoryBean automatically supports Spring transaction
57  * management for the Hibernate3 <code>getCurrentSession()</code> method.)
58  *
59  * <p>The central method is <code>execute</code>, supporting Hibernate access code
60  * implementing the {@link HibernateCallback} interface. It provides Hibernate Session
61  * handling such that neither the HibernateCallback implementation nor the calling
62  * code needs to explicitly care about retrieving/closing Hibernate Sessions,
63  * or handling Session lifecycle exceptions. For typical single step actions,
64  * there are various convenience methods (find, load, saveOrUpdate, delete).
65  *
66  * <p>Can be used within a service implementation via direct instantiation
67  * with a SessionFactory reference, or get prepared in an application context
68  * and given to services as bean reference. Note: The SessionFactory should
69  * always be configured as bean in the application context, in the first case
70  * given to the service directly, in the second case to the prepared template.
71  *
72  * <p>This class can be considered as direct alternative to working with the raw
73  * Hibernate3 Session API (through <code>SessionFactory.getCurrentSession()</code>).
74  * The major advantage is its automatic conversion to DataAccessExceptions, the
75  * major disadvantage that no checked application exceptions can get thrown from
76  * within data access code. Corresponding checks and the actual throwing of such
77  * exceptions can often be deferred to after callback execution, though.
78  *
79  * <p>Note that even if {@link HibernateTransactionManager} is used for transaction
80  * demarcation in higher-level services, all those services above the data
81  * access layer don't need to be Hibernate-aware. Setting such a special
82  * PlatformTransactionManager is a configuration issue: For example,
83  * switching to JTA is just a matter of Spring configuration (use
84  * JtaTransactionManager instead) that does not affect application code.
85  *
86  * <p>{@link LocalSessionFactoryBean} is the preferred way of obtaining a reference
87  * to a specific Hibernate SessionFactory, at least in a non-EJB environment.
88  * The Spring application context will manage its lifecycle, initializing and
89  * shutting down the factory as part of the application.
90  *
91  * <p>Note that operations that return an Iterator (i.e. <code>iterate</code>)
92  * are supposed to be used within Spring-driven or JTA-driven transactions
93  * (with HibernateTransactionManager, JtaTransactionManager, or EJB CMT).
94  * Else, the Iterator won't be able to read results from its ResultSet anymore,
95  * as the underlying Hibernate Session will already have been closed.
96  *
97  * <p>Lazy loading will also just work with an open Hibernate Session,
98  * either within a transaction or within OpenSessionInViewFilter/Interceptor.
99  * Furthermore, some operations just make sense within transactions,
100  * for example: <code>contains</code>, <code>evict</code>, <code>lock</code>,
101  * <code>flush</code>, <code>clear</code>.
102  *
103  * @author Juergen Hoeller
104  * @since 1.2
105  * @see org.hibernate.SessionFactory#getCurrentSession()
106  * @see #setSessionFactory
107  * @see HibernateCallback
108  * @see org.hibernate.Session
109  * @see LocalSessionFactoryBean
110  * @see HibernateTransactionManager
111  * @see org.springframework.transaction.jta.JtaTransactionManager
112  * @see org.springframework.orm.hibernate3.support.OpenSessionInViewFilter
113  * @see org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor
114  */

115 public class HibernateTemplate extends HibernateAccessor implements HibernateOperations {
116
117     private boolean allowCreate = true;
118
119     private boolean alwaysUseNewSession = false;
120
121     private boolean exposeNativeSession = false;
122
123     private boolean checkWriteOperations = true;
124
125     private boolean cacheQueries = false;
126
127     private String JavaDoc queryCacheRegion;
128
129     private int fetchSize = 0;
130
131     private int maxResults = 0;
132
133
134     /**
135      * Create a new HibernateTemplate instance.
136      */

137     public HibernateTemplate() {
138     }
139
140     /**
141      * Create a new HibernateTemplate instance.
142      * @param sessionFactory SessionFactory to create Sessions
143      */

144     public HibernateTemplate(SessionFactory sessionFactory) {
145         setSessionFactory(sessionFactory);
146         afterPropertiesSet();
147     }
148
149     /**
150      * Create a new HibernateTemplate instance.
151      * @param sessionFactory SessionFactory to create Sessions
152      * @param allowCreate if a non-transactional Session should be created when no
153      * transactional Session can be found for the current thread
154      */

155     public HibernateTemplate(SessionFactory sessionFactory, boolean allowCreate) {
156         setSessionFactory(sessionFactory);
157         setAllowCreate(allowCreate);
158         afterPropertiesSet();
159     }
160
161
162     /**
163      * Set if a new Session should be created when no transactional Session
164      * can be found for the current thread.
165      * <p>HibernateTemplate is aware of a corresponding Session bound to the
166      * current thread, for example when using HibernateTransactionManager.
167      * If allowCreate is true, a new non-transactional Session will be created
168      * if none found, which needs to be closed at the end of the operation.
169      * If false, an IllegalStateException will get thrown in this case.
170      * @see SessionFactoryUtils#getSession(SessionFactory, boolean)
171      */

172     public void setAllowCreate(boolean allowCreate) {
173         this.allowCreate = allowCreate;
174     }
175
176     /**
177      * Return if a new Session should be created if no thread-bound found.
178      */

179     public boolean isAllowCreate() {
180         return this.allowCreate;
181     }
182
183     /**
184      * Set whether to always use a new Hibernate Session for this template.
185      * Default is "false"; if activated, all operations on this template will
186      * work on a new Hibernate Session even in case of a pre-bound Session
187      * (for example, within a transaction or OpenSessionInViewFilter).
188      * <p>Within a transaction, a new Hibernate Session used by this template
189      * will participate in the transaction through using the same JDBC
190      * Connection. In such a scenario, multiple Sessions will participate
191      * in the same database transaction.
192      * <p>Turn this on for operations that are supposed to always execute
193      * independently, without side effects caused by a shared Hibernate Session.
194      */

195     public void setAlwaysUseNewSession(boolean alwaysUseNewSession) {
196         this.alwaysUseNewSession = alwaysUseNewSession;
197     }
198
199     /**
200      * Return whether to always use a new Hibernate Session for this template.
201      */

202     public boolean isAlwaysUseNewSession() {
203         return this.alwaysUseNewSession;
204     }
205
206     /**
207      * Set whether to expose the native Hibernate Session to
208      * HibernateCallback code.
209      * <p>Default is "false": a Session proxy will be returned, suppressing
210      * <code>close</code> calls and automatically applying query cache
211      * settings and transaction timeouts.
212      * @see HibernateCallback
213      * @see org.hibernate.Session
214      * @see #setCacheQueries
215      * @see #setQueryCacheRegion
216      * @see #prepareQuery
217      * @see #prepareCriteria
218      */

219     public void setExposeNativeSession(boolean exposeNativeSession) {
220         this.exposeNativeSession = exposeNativeSession;
221     }
222
223     /**
224      * Return whether to expose the native Hibernate Session to
225      * HibernateCallback code, or rather a Session proxy.
226      */

227     public boolean isExposeNativeSession() {
228         return this.exposeNativeSession;
229     }
230
231     /**
232      * Set whether to check that the Hibernate Session is not in read-only mode
233      * in case of write operations (save/update/delete).
234      * <p>Default is "true", for fail-fast behavior when attempting write operations
235      * within a read-only transaction. Turn this off to allow save/update/delete
236      * on a Session with flush mode NEVER.
237      * @see #setFlushMode
238      * @see #checkWriteOperationAllowed
239      * @see org.springframework.transaction.TransactionDefinition#isReadOnly
240      */

241     public void setCheckWriteOperations(boolean checkWriteOperations) {
242         this.checkWriteOperations = checkWriteOperations;
243     }
244
245     /**
246      * Return whether to check that the Hibernate Session is not in read-only
247      * mode in case of write operations (save/update/delete).
248      */

249     public boolean isCheckWriteOperations() {
250         return this.checkWriteOperations;
251     }
252
253     /**
254      * Set whether to cache all queries executed by this template.
255      * <p>If this is "true", all Query and Criteria objects created by
256      * this template will be marked as cacheable (including all
257      * queries through find methods).
258      * <p>To specify the query region to be used for queries cached
259      * by this template, set the "queryCacheRegion" property.
260      * @see #setQueryCacheRegion
261      * @see org.hibernate.Query#setCacheable
262      * @see org.hibernate.Criteria#setCacheable
263      */

264     public void setCacheQueries(boolean cacheQueries) {
265         this.cacheQueries = cacheQueries;
266     }
267
268     /**
269      * Return whether to cache all queries executed by this template.
270      */

271     public boolean isCacheQueries() {
272         return this.cacheQueries;
273     }
274
275     /**
276      * Set the name of the cache region for queries executed by this template.
277      * <p>If this is specified, it will be applied to all Query and Criteria objects
278      * created by this template (including all queries through find methods).
279      * <p>The cache region will not take effect unless queries created by this
280      * template are configured to be cached via the "cacheQueries" property.
281      * @see #setCacheQueries
282      * @see org.hibernate.Query#setCacheRegion
283      * @see org.hibernate.Criteria#setCacheRegion
284      */

285     public void setQueryCacheRegion(String JavaDoc queryCacheRegion) {
286         this.queryCacheRegion = queryCacheRegion;
287     }
288
289     /**
290      * Return the name of the cache region for queries executed by this template.
291      */

292     public String JavaDoc getQueryCacheRegion() {
293         return this.queryCacheRegion;
294     }
295
296     /**
297      * Set the fetch size for this HibernateTemplate. This is important for processing
298      * large result sets: Setting this higher than the default value will increase
299      * processing speed at the cost of memory consumption; setting this lower can
300      * avoid transferring row data that will never be read by the application.
301      * <p>Default is 0, indicating to use the JDBC driver's default.
302      */

303     public void setFetchSize(int fetchSize) {
304         this.fetchSize = fetchSize;
305     }
306
307     /**
308      * Return the fetch size specified for this HibernateTemplate.
309      */

310     public int getFetchSize() {
311         return this.fetchSize;
312     }
313
314     /**
315      * Set the maximum number of rows for this HibernateTemplate. This is important
316      * for processing subsets of large result sets, avoiding to read and hold
317      * the entire result set in the database or in the JDBC driver if we're
318      * never interested in the entire result in the first place (for example,
319      * when performing searches that might return a large number of matches).
320      * <p>Default is 0, indicating to use the JDBC driver's default.
321      */

322     public void setMaxResults(int maxResults) {
323         this.maxResults = maxResults;
324     }
325
326     /**
327      * Return the maximum number of rows specified for this HibernateTemplate.
328      */

329     public int getMaxResults() {
330         return this.maxResults;
331     }
332
333
334     public Object JavaDoc execute(HibernateCallback action) throws DataAccessException {
335         return execute(action, isExposeNativeSession());
336     }
337
338     public List JavaDoc executeFind(HibernateCallback action) throws DataAccessException {
339         Object JavaDoc result = execute(action, isExposeNativeSession());
340         if (result != null && !(result instanceof List JavaDoc)) {
341             throw new InvalidDataAccessApiUsageException(
342                     "Result object returned from HibernateCallback isn't a List: [" + result + "]");
343         }
344         return (List JavaDoc) result;
345     }
346
347     /**
348      * Execute the action specified by the given action object within a Session.
349      * @param action callback object that specifies the Hibernate action
350      * @param exposeNativeSession whether to expose the native Hibernate Session
351      * to callback code
352      * @return a result object returned by the action, or <code>null</code>
353      * @throws org.springframework.dao.DataAccessException in case of Hibernate errors
354      */

355     public Object JavaDoc execute(HibernateCallback action, boolean exposeNativeSession) throws DataAccessException {
356         Assert.notNull(action, "Callback object must not be null");
357
358         Session session = getSession();
359         boolean existingTransaction = SessionFactoryUtils.isSessionTransactional(session, getSessionFactory());
360         if (existingTransaction) {
361             logger.debug("Found thread-bound Session for HibernateTemplate");
362         }
363
364         FlushMode previousFlushMode = null;
365         try {
366             previousFlushMode = applyFlushMode(session, existingTransaction);
367             enableFilters(session);
368             Session sessionToExpose = (exposeNativeSession ? session : createSessionProxy(session));
369             Object JavaDoc result = action.doInHibernate(sessionToExpose);
370             flushIfNecessary(session, existingTransaction);
371             return result;
372         }
373         catch (HibernateException ex) {
374             throw convertHibernateAccessException(ex);
375         }
376         catch (SQLException JavaDoc ex) {
377             throw convertJdbcAccessException(ex);
378         }
379         catch (RuntimeException JavaDoc ex) {
380             // Callback code threw application exception...
381
throw ex;
382         }
383         finally {
384             if (existingTransaction) {
385                 logger.debug("Not closing pre-bound Hibernate Session after HibernateTemplate");
386                 disableFilters(session);
387                 if (previousFlushMode != null) {
388                     session.setFlushMode(previousFlushMode);
389                 }
390             }
391             else {
392                 // Never use deferred close for an explicitly new Session.
393
if (isAlwaysUseNewSession()) {
394                     SessionFactoryUtils.closeSession(session);
395                 }
396                 else {
397                     SessionFactoryUtils.closeSessionOrRegisterDeferredClose(session, getSessionFactory());
398                 }
399             }
400         }
401     }
402
403     /**
404      * Return a Session for use by this template.
405      * <p>Returns a new Session in case of "alwaysUseNewSession" (using the same
406      * JDBC Connection as a transactional Session, if applicable), a pre-bound
407      * Session in case of "allowCreate" turned off, and a pre-bound or new Session
408      * else (new only if no transactional or otherwise pre-bound Session exists).
409      * @see SessionFactoryUtils#getSession
410      * @see SessionFactoryUtils#getNewSession
411      * @see #setAlwaysUseNewSession
412      * @see #setAllowCreate
413      */

414     protected Session getSession() {
415         if (isAlwaysUseNewSession()) {
416             return SessionFactoryUtils.getNewSession(getSessionFactory(), getEntityInterceptor());
417         }
418         else if (!isAllowCreate()) {
419             return SessionFactoryUtils.getSession(getSessionFactory(), false);
420         }
421         else {
422             return SessionFactoryUtils.getSession(
423                     getSessionFactory(), getEntityInterceptor(), getJdbcExceptionTranslator());
424         }
425     }
426
427     /**
428      * Create a close-suppressing proxy for the given Hibernate Session.
429      * The proxy also prepares returned Query and Criteria objects.
430      * @param session the Hibernate Session to create a proxy for
431      * @return the Session proxy
432      * @see org.hibernate.Session#close()
433      * @see #prepareQuery
434      * @see #prepareCriteria
435      */

436     protected Session createSessionProxy(Session session) {
437         Class JavaDoc[] sessionIfcs = null;
438         if (session instanceof SessionImplementor) {
439             sessionIfcs = new Class JavaDoc[] {Session.class, SessionImplementor.class};
440         }
441         else {
442             sessionIfcs = new Class JavaDoc[] {Session.class};
443         }
444         return (Session) Proxy.newProxyInstance(
445                 getClass().getClassLoader(), sessionIfcs,
446                 new CloseSuppressingInvocationHandler(session));
447     }
448
449
450     //-------------------------------------------------------------------------
451
// Convenience methods for loading individual objects
452
//-------------------------------------------------------------------------
453

454     public Object JavaDoc get(Class JavaDoc entityClass, Serializable JavaDoc id) throws DataAccessException {
455         return get(entityClass, id, null);
456     }
457
458     public Object JavaDoc get(final Class JavaDoc entityClass, final Serializable JavaDoc id, final LockMode lockMode)
459             throws DataAccessException {
460
461         return execute(new HibernateCallback() {
462             public Object JavaDoc doInHibernate(Session session) throws HibernateException {
463                 if (lockMode != null) {
464                     return session.get(entityClass, id, lockMode);
465                 }
466                 else {
467                     return session.get(entityClass, id);
468                 }
469             }
470         }, true);
471     }
472
473     public Object JavaDoc get(String JavaDoc entityName, Serializable JavaDoc id) throws DataAccessException {
474         return get(entityName, id, null);
475     }
476
477     public Object JavaDoc get(final String JavaDoc entityName, final Serializable JavaDoc id, final LockMode lockMode)
478             throws DataAccessException {
479
480         return execute(new HibernateCallback() {
481             public Object JavaDoc doInHibernate(Session session) throws HibernateException {
482                 if (lockMode != null) {
483                     return session.get(entityName, id, lockMode);
484                 }
485                 else {
486                     return session.get(entityName, id);
487                 }
488             }
489         }, true);
490     }
491
492     public Object JavaDoc load(Class JavaDoc entityClass, Serializable JavaDoc id) throws DataAccessException {
493         return load(entityClass, id, null);
494     }
495
496     public Object JavaDoc load(final Class JavaDoc entityClass, final Serializable JavaDoc id, final LockMode lockMode)
497             throws DataAccessException {
498
499         return execute(new HibernateCallback() {
500             public Object JavaDoc doInHibernate(Session session) throws HibernateException {
501                 if (lockMode != null) {
502                     return session.load(entityClass, id, lockMode);
503                 }
504                 else {
505                     return session.load(entityClass, id);
506                 }
507             }
508         }, true);
509     }
510
511     public Object JavaDoc load(String JavaDoc entityName, Serializable JavaDoc id) throws DataAccessException {
512         return load(entityName, id, null);
513     }
514
515     public Object JavaDoc load(final String JavaDoc entityName, final Serializable JavaDoc id, final LockMode lockMode)
516             throws DataAccessException {
517
518         return execute(new HibernateCallback() {
519             public Object JavaDoc doInHibernate(Session session) throws HibernateException {
520                 if (lockMode != null) {
521                     return session.load(entityName, id, lockMode);
522                 }
523                 else {
524                     return session.load(entityName, id);
525                 }
526             }
527         }, true);
528     }
529
530     public List JavaDoc loadAll(final Class JavaDoc entityClass) throws DataAccessException {
531         return (List JavaDoc) execute(new HibernateCallback() {
532             public Object JavaDoc doInHibernate(Session session) throws HibernateException {
533                 Criteria criteria = session.createCriteria(entityClass);
534                 prepareCriteria(criteria);
535                 return criteria.list();
536             }
537         }, true);
538     }
539
540     public void load(final Object JavaDoc entity, final Serializable JavaDoc id) throws DataAccessException {
541         execute(new HibernateCallback() {
542             public Object JavaDoc doInHibernate(Session session) throws HibernateException {
543                 session.load(entity, id);
544                 return null;
545             }
546         }, true);
547     }
548
549     public void refresh(final Object JavaDoc entity) throws DataAccessException {
550         refresh(entity, null);
551     }
552
553     public void refresh(final Object JavaDoc entity, final LockMode lockMode) throws DataAccessException {
554         execute(new HibernateCallback() {
555             public Object JavaDoc doInHibernate(Session session) throws HibernateException {
556                 if (lockMode != null) {
557                     session.refresh(entity, lockMode);
558                 }
559                 else {
560                     session.refresh(entity);
561                 }
562                 return null;
563             }
564         }, true);
565     }
566
567     public boolean contains(final Object JavaDoc entity) throws DataAccessException {
568         Boolean JavaDoc result = (Boolean JavaDoc) execute(new HibernateCallback() {
569             public Object JavaDoc doInHibernate(Session session) {
570                 return (session.contains(entity) ? Boolean.TRUE : Boolean.FALSE);
571             }
572         }, true);
573         return result.booleanValue();
574     }
575
576     public void evict(final Object JavaDoc entity) throws DataAccessException {
577         execute(new HibernateCallback() {
578             public Object JavaDoc doInHibernate(Session session) throws HibernateException {
579                 session.evict(entity);
580                 return null;
581             }
582         }, true);
583     }
584
585     public void initialize(Object JavaDoc proxy) throws DataAccessException {
586         try {
587             Hibernate.initialize(proxy);
588         }
589         catch (HibernateException ex) {
590             throw SessionFactoryUtils.convertHibernateAccessException(ex);
591         }
592     }
593
594     public Filter enableFilter(String JavaDoc filterName) throws IllegalStateException JavaDoc {
595         Session session = SessionFactoryUtils.getSession(getSessionFactory(), false);
596         Filter filter = session.getEnabledFilter(filterName);
597         if (filter == null) {
598             filter = session.enableFilter(filterName);
599         }
600         return filter;
601     }
602
603
604     //-------------------------------------------------------------------------
605
// Convenience methods for storing individual objects
606
//-------------------------------------------------------------------------
607

608     public void lock(final Object JavaDoc entity, final LockMode lockMode) throws DataAccessException {
609         execute(new HibernateCallback() {
610             public Object JavaDoc doInHibernate(Session session) throws HibernateException {
611                 session.lock(entity, lockMode);
612                 return null;
613             }
614         }, true);
615     }
616
617     public void lock(final String JavaDoc entityName, final Object JavaDoc entity, final LockMode lockMode)
618             throws DataAccessException {
619
620         execute(new HibernateCallback() {
621             public Object JavaDoc doInHibernate(Session session) throws HibernateException {
622                 session.lock(entityName, entity, lockMode);
623                 return null;
624             }
625         }, true);
626     }
627
628     public Serializable JavaDoc save(final Object JavaDoc entity) throws DataAccessException {
629         return (Serializable JavaDoc) execute(new HibernateCallback() {
630             public Object JavaDoc doInHibernate(Session session) throws HibernateException {
631                 checkWriteOperationAllowed(session);
632                 return session.save(entity);
633             }
634         }, true);
635     }
636
637     public Serializable JavaDoc save(final String JavaDoc entityName, final Object JavaDoc entity) throws DataAccessException {
638         return (Serializable JavaDoc) execute(new HibernateCallback() {
639             public Object JavaDoc doInHibernate(Session session) throws HibernateException {
640                 checkWriteOperationAllowed(session);
641                 return session.save(entityName, entity);
642             }
643         }, true);
644     }
645
646     public void update(Object JavaDoc entity) throws DataAccessException {
647         update(entity, null);
648     }
649
650     public void update(final Object JavaDoc entity, final LockMode lockMode) throws DataAccessException {
651         execute(new HibernateCallback() {
652             public Object JavaDoc doInHibernate(Session session) throws HibernateException {
653                 checkWriteOperationAllowed(session);
654                 session.update(entity);
655                 if (lockMode != null) {
656                     session.lock(entity, lockMode);
657                 }
658                 return null;
659             }
660         }, true);
661     }
662
663     public void update(String JavaDoc entityName, Object JavaDoc entity) throws DataAccessException {
664         update(entityName, entity, null);
665     }
666
667     public void update(final String JavaDoc entityName, final Object JavaDoc entity, final LockMode lockMode)
668             throws DataAccessException {
669
670         execute(new HibernateCallback() {
671             public Object JavaDoc doInHibernate(Session session) throws HibernateException {
672                 checkWriteOperationAllowed(session);
673                 session.update(entityName, entity);
674                 if (lockMode != null) {
675                     session.lock(entity, lockMode);
676                 }
677                 return null;
678             }
679         }, true);
680     }
681
682     public void saveOrUpdate(final Object JavaDoc entity) throws DataAccessException {
683         execute(new HibernateCallback() {
684             public Object JavaDoc doInHibernate(Session session) throws HibernateException {
685                 checkWriteOperationAllowed(session);
686                 session.saveOrUpdate(entity);
687                 return null;
688             }
689         }, true);
690     }
691
692     public void saveOrUpdate(final String JavaDoc entityName, final Object JavaDoc entity) throws DataAccessException {
693         execute(new HibernateCallback() {
694             public Object JavaDoc doInHibernate(Session session) throws HibernateException {
695                 checkWriteOperationAllowed(session);
696                 session.saveOrUpdate(entityName, entity);
697                 return null;
698             }
699         }, true);
700     }
701
702     public void saveOrUpdateAll(final Collection JavaDoc entities) throws DataAccessException {
703         execute(new HibernateCallback() {
704             public Object JavaDoc doInHibernate(Session session) throws HibernateException {
705                 checkWriteOperationAllowed(session);
706                 for (Iterator JavaDoc it = entities.iterator(); it.hasNext();) {
707                     session.saveOrUpdate(it.next());
708                 }
709                 return null;
710             }
711         }, true);
712     }
713
714     public void replicate(final Object JavaDoc entity, final ReplicationMode replicationMode)
715             throws DataAccessException {
716
717         execute(new HibernateCallback() {
718             public Object JavaDoc doInHibernate(Session session) throws HibernateException {
719                 checkWriteOperationAllowed(session);
720                 session.replicate(entity, replicationMode);
721                 return null;
722             }
723         }, true);
724     }
725
726     public void replicate(final String JavaDoc entityName, final Object JavaDoc entity, final ReplicationMode replicationMode)
727             throws DataAccessException {
728
729         execute(new HibernateCallback() {
730             public Object JavaDoc doInHibernate(Session session) throws HibernateException {
731                 checkWriteOperationAllowed(session);
732                 session.replicate(entityName, entity, replicationMode);
733                 return null;
734             }
735         }, true);
736     }
737
738     public void persist(final Object JavaDoc entity) throws DataAccessException {
739         execute(new HibernateCallback() {
740             public Object JavaDoc doInHibernate(Session session) throws HibernateException {
741                 checkWriteOperationAllowed(session);
742                 session.persist(entity);
743                 return null;
744             }
745         }, true);
746     }
747
748     public void persist(final String JavaDoc entityName, final Object JavaDoc entity) throws