Source Code Cross Referenced for SessionFactoryUtils.java in  » J2EE » spring-framework-2.5 » org » springframework » orm » hibernate3 » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » J2EE » spring framework 2.5 » org.springframework.orm.hibernate3 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


001:        /*
002:         * Copyright 2002-2007 the original author or authors.
003:         *
004:         * Licensed under the Apache License, Version 2.0 (the "License");
005:         * you may not use this file except in compliance with the License.
006:         * You may obtain a copy of the License at
007:         *
008:         *      http://www.apache.org/licenses/LICENSE-2.0
009:         *
010:         * Unless required by applicable law or agreed to in writing, software
011:         * distributed under the License is distributed on an "AS IS" BASIS,
012:         * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013:         * See the License for the specific language governing permissions and
014:         * limitations under the License.
015:         */
016:
017:        package org.springframework.orm.hibernate3;
018:
019:        import java.util.HashMap;
020:        import java.util.Iterator;
021:        import java.util.LinkedHashSet;
022:        import java.util.Map;
023:        import java.util.Set;
024:
025:        import javax.sql.DataSource;
026:        import javax.transaction.Status;
027:        import javax.transaction.Transaction;
028:        import javax.transaction.TransactionManager;
029:
030:        import org.apache.commons.logging.Log;
031:        import org.apache.commons.logging.LogFactory;
032:        import org.hibernate.Criteria;
033:        import org.hibernate.FlushMode;
034:        import org.hibernate.HibernateException;
035:        import org.hibernate.Interceptor;
036:        import org.hibernate.JDBCException;
037:        import org.hibernate.NonUniqueResultException;
038:        import org.hibernate.ObjectDeletedException;
039:        import org.hibernate.PersistentObjectException;
040:        import org.hibernate.PropertyValueException;
041:        import org.hibernate.Query;
042:        import org.hibernate.QueryException;
043:        import org.hibernate.Session;
044:        import org.hibernate.SessionFactory;
045:        import org.hibernate.StaleObjectStateException;
046:        import org.hibernate.StaleStateException;
047:        import org.hibernate.TransientObjectException;
048:        import org.hibernate.UnresolvableObjectException;
049:        import org.hibernate.WrongClassException;
050:        import org.hibernate.connection.ConnectionProvider;
051:        import org.hibernate.engine.SessionFactoryImplementor;
052:        import org.hibernate.exception.ConstraintViolationException;
053:        import org.hibernate.exception.DataException;
054:        import org.hibernate.exception.JDBCConnectionException;
055:        import org.hibernate.exception.LockAcquisitionException;
056:        import org.hibernate.exception.SQLGrammarException;
057:
058:        import org.springframework.dao.CannotAcquireLockException;
059:        import org.springframework.dao.DataAccessException;
060:        import org.springframework.dao.DataAccessResourceFailureException;
061:        import org.springframework.dao.DataIntegrityViolationException;
062:        import org.springframework.dao.IncorrectResultSizeDataAccessException;
063:        import org.springframework.dao.InvalidDataAccessApiUsageException;
064:        import org.springframework.dao.InvalidDataAccessResourceUsageException;
065:        import org.springframework.jdbc.datasource.DataSourceUtils;
066:        import org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator;
067:        import org.springframework.jdbc.support.SQLExceptionTranslator;
068:        import org.springframework.jdbc.support.SQLStateSQLExceptionTranslator;
069:        import org.springframework.transaction.jta.SpringJtaSynchronizationAdapter;
070:        import org.springframework.transaction.support.TransactionSynchronizationManager;
071:        import org.springframework.util.Assert;
072:
073:        /**
074:         * Helper class featuring methods for Hibernate Session handling,
075:         * allowing for reuse of Hibernate Session instances within transactions.
076:         * Also provides support for exception translation.
077:         *
078:         * <p>Supports synchronization with both Spring-managed JTA transactions
079:         * (see {@link org.springframework.transaction.jta.JtaTransactionManager})
080:         * and non-Spring JTA transactions (i.e. plain JTA or EJB CMT),
081:         * transparently providing transaction-scoped Hibernate Sessions.
082:         * Note that for non-Spring JTA transactions, a JTA TransactionManagerLookup
083:         * has to be specified in the Hibernate configuration.
084:         *
085:         * <p>Used internally by {@link HibernateTemplate}, {@link HibernateInterceptor}
086:         * and {@link HibernateTransactionManager}. Can also be used directly in
087:         * application code.
088:         *
089:         * @author Juergen Hoeller
090:         * @since 1.2
091:         * @see #getSession
092:         * @see #releaseSession
093:         * @see HibernateTransactionManager
094:         * @see org.springframework.transaction.jta.JtaTransactionManager
095:         * @see org.springframework.transaction.support.TransactionSynchronizationManager
096:         */
097:        public abstract class SessionFactoryUtils {
098:
099:            /**
100:             * Order value for TransactionSynchronization objects that clean up Hibernate Sessions.
101:             * Returns <code>DataSourceUtils.CONNECTION_SYNCHRONIZATION_ORDER - 100</code>
102:             * to execute Session cleanup before JDBC Connection cleanup, if any.
103:             * @see org.springframework.jdbc.datasource.DataSourceUtils#CONNECTION_SYNCHRONIZATION_ORDER
104:             */
105:            public static final int SESSION_SYNCHRONIZATION_ORDER = DataSourceUtils.CONNECTION_SYNCHRONIZATION_ORDER - 100;
106:
107:            static final Log logger = LogFactory
108:                    .getLog(SessionFactoryUtils.class);
109:
110:            private static final ThreadLocal deferredCloseHolder = new ThreadLocal();
111:
112:            /**
113:             * Determine the DataSource of the given SessionFactory.
114:             * @param sessionFactory the SessionFactory to check
115:             * @return the DataSource, or <code>null</code> if none found
116:             * @see org.hibernate.engine.SessionFactoryImplementor#getConnectionProvider
117:             * @see LocalDataSourceConnectionProvider
118:             */
119:            public static DataSource getDataSource(SessionFactory sessionFactory) {
120:                if (sessionFactory instanceof  SessionFactoryImplementor) {
121:                    ConnectionProvider cp = ((SessionFactoryImplementor) sessionFactory)
122:                            .getConnectionProvider();
123:                    if (cp instanceof  LocalDataSourceConnectionProvider) {
124:                        return ((LocalDataSourceConnectionProvider) cp)
125:                                .getDataSource();
126:                    }
127:                }
128:                return null;
129:            }
130:
131:            /**
132:             * Create an appropriate SQLExceptionTranslator for the given SessionFactory.
133:             * If a DataSource is found, a SQLErrorCodeSQLExceptionTranslator for the DataSource
134:             * is created; else, a SQLStateSQLExceptionTranslator as fallback.
135:             * @param sessionFactory the SessionFactory to create the translator for
136:             * @return the SQLExceptionTranslator
137:             * @see #getDataSource
138:             * @see org.springframework.jdbc.support.SQLErrorCodeSQLExceptionTranslator
139:             * @see org.springframework.jdbc.support.SQLStateSQLExceptionTranslator
140:             */
141:            public static SQLExceptionTranslator newJdbcExceptionTranslator(
142:                    SessionFactory sessionFactory) {
143:                DataSource ds = getDataSource(sessionFactory);
144:                if (ds != null) {
145:                    return new SQLErrorCodeSQLExceptionTranslator(ds);
146:                }
147:                return new SQLStateSQLExceptionTranslator();
148:            }
149:
150:            /**
151:             * Try to retrieve the JTA TransactionManager from the given SessionFactory
152:             * and/or Session. Check the passed-in SessionFactory for implementing
153:             * SessionFactoryImplementor (the usual case), falling back to the
154:             * SessionFactory reference that the Session itself carries.
155:             * @param sessionFactory Hibernate SessionFactory
156:             * @param session Hibernate Session (can also be <code>null</code>)
157:             * @return the JTA TransactionManager, if any
158:             * @see javax.transaction.TransactionManager
159:             * @see SessionFactoryImplementor#getTransactionManager
160:             * @see Session#getSessionFactory
161:             * @see org.hibernate.impl.SessionFactoryImpl
162:             */
163:            public static TransactionManager getJtaTransactionManager(
164:                    SessionFactory sessionFactory, Session session) {
165:                SessionFactoryImplementor sessionFactoryImpl = null;
166:                if (sessionFactory instanceof  SessionFactoryImplementor) {
167:                    sessionFactoryImpl = ((SessionFactoryImplementor) sessionFactory);
168:                } else if (session != null) {
169:                    SessionFactory internalFactory = session
170:                            .getSessionFactory();
171:                    if (internalFactory instanceof  SessionFactoryImplementor) {
172:                        sessionFactoryImpl = (SessionFactoryImplementor) internalFactory;
173:                    }
174:                }
175:                return (sessionFactoryImpl != null ? sessionFactoryImpl
176:                        .getTransactionManager() : null);
177:            }
178:
179:            /**
180:             * Get a Hibernate Session for the given SessionFactory. Is aware of and will
181:             * return any existing corresponding Session bound to the current thread, for
182:             * example when using {@link HibernateTransactionManager}. Will create a new
183:             * Session otherwise, if "allowCreate" is <code>true</code>.
184:             * <p>This is the <code>getSession</code> method used by typical data access code,
185:             * in combination with <code>releaseSession</code> called when done with
186:             * the Session. Note that HibernateTemplate allows to write data access code
187:             * without caring about such resource handling.
188:             * @param sessionFactory Hibernate SessionFactory to create the session with
189:             * @param allowCreate whether a non-transactional Session should be created
190:             * when no transactional Session can be found for the current thread
191:             * @return the Hibernate Session
192:             * @throws DataAccessResourceFailureException if the Session couldn't be created
193:             * @throws IllegalStateException if no thread-bound Session found and
194:             * "allowCreate" is <code>false</code>
195:             * @see #getSession(SessionFactory, Interceptor, SQLExceptionTranslator)
196:             * @see #releaseSession
197:             * @see HibernateTemplate
198:             */
199:            public static Session getSession(SessionFactory sessionFactory,
200:                    boolean allowCreate)
201:                    throws DataAccessResourceFailureException,
202:                    IllegalStateException {
203:
204:                try {
205:                    return doGetSession(sessionFactory, null, null, allowCreate);
206:                } catch (HibernateException ex) {
207:                    throw new DataAccessResourceFailureException(
208:                            "Could not open Hibernate Session", ex);
209:                }
210:            }
211:
212:            /**
213:             * Get a Hibernate Session for the given SessionFactory. Is aware of and will
214:             * return any existing corresponding Session bound to the current thread, for
215:             * example when using {@link HibernateTransactionManager}. Will always create
216:             * a new Session otherwise.
217:             * <p>Supports setting a Session-level Hibernate entity interceptor that allows
218:             * to inspect and change property values before writing to and reading from the
219:             * database. Such an interceptor can also be set at the SessionFactory level
220:             * (i.e. on LocalSessionFactoryBean), on HibernateTransactionManager, or on
221:             * HibernateInterceptor/HibernateTemplate.
222:             * @param sessionFactory Hibernate SessionFactory to create the session with
223:             * @param entityInterceptor Hibernate entity interceptor, or <code>null</code> if none
224:             * @param jdbcExceptionTranslator SQLExcepionTranslator to use for flushing the
225:             * Session on transaction synchronization (may be <code>null</code>; only used
226:             * when actually registering a transaction synchronization)
227:             * @return the Hibernate Session
228:             * @throws DataAccessResourceFailureException if the Session couldn't be created
229:             * @see LocalSessionFactoryBean#setEntityInterceptor
230:             * @see HibernateInterceptor#setEntityInterceptor
231:             * @see HibernateTemplate#setEntityInterceptor
232:             */
233:            public static Session getSession(SessionFactory sessionFactory,
234:                    Interceptor entityInterceptor,
235:                    SQLExceptionTranslator jdbcExceptionTranslator)
236:                    throws DataAccessResourceFailureException {
237:
238:                try {
239:                    return doGetSession(sessionFactory, entityInterceptor,
240:                            jdbcExceptionTranslator, true);
241:                } catch (HibernateException ex) {
242:                    throw new DataAccessResourceFailureException(
243:                            "Could not open Hibernate Session", ex);
244:                }
245:            }
246:
247:            /**
248:             * Get a Hibernate Session for the given SessionFactory. Is aware of and will
249:             * return any existing corresponding Session bound to the current thread, for
250:             * example when using {@link HibernateTransactionManager}. Will create a new
251:             * Session otherwise, if "allowCreate" is <code>true</code>.
252:             * <p>Throws the original HibernateException, in contrast to {@link #getSession}.
253:             * @param sessionFactory Hibernate SessionFactory to create the session with
254:             * @param allowCreate whether a non-transactional Session should be created
255:             * when no transactional Session can be found for the current thread
256:             * @return the Hibernate Session
257:             * @throws HibernateException if the Session couldn't be created
258:             * @throws IllegalStateException if no thread-bound Session found and allowCreate false
259:             */
260:            public static Session doGetSession(SessionFactory sessionFactory,
261:                    boolean allowCreate) throws HibernateException,
262:                    IllegalStateException {
263:
264:                return doGetSession(sessionFactory, null, null, allowCreate);
265:            }
266:
267:            /**
268:             * Get a Hibernate Session for the given SessionFactory. Is aware of and will
269:             * return any existing corresponding Session bound to the current thread, for
270:             * example when using {@link HibernateTransactionManager}. Will create a new
271:             * Session otherwise, if "allowCreate" is <code>true</code>.
272:             * <p>Same as {@link #getSession}, but throwing the original HibernateException.
273:             * @param sessionFactory Hibernate SessionFactory to create the session with
274:             * @param entityInterceptor Hibernate entity interceptor, or <code>null</code> if none
275:             * @param jdbcExceptionTranslator SQLExcepionTranslator to use for flushing the
276:             * Session on transaction synchronization (may be <code>null</code>)
277:             * @param allowCreate whether a non-transactional Session should be created
278:             * when no transactional Session can be found for the current thread
279:             * @return the Hibernate Session
280:             * @throws HibernateException if the Session couldn't be created
281:             * @throws IllegalStateException if no thread-bound Session found and
282:             * "allowCreate" is <code>false</code>
283:             */
284:            private static Session doGetSession(SessionFactory sessionFactory,
285:                    Interceptor entityInterceptor,
286:                    SQLExceptionTranslator jdbcExceptionTranslator,
287:                    boolean allowCreate) throws HibernateException,
288:                    IllegalStateException {
289:
290:                Assert.notNull(sessionFactory, "No SessionFactory specified");
291:
292:                SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager
293:                        .getResource(sessionFactory);
294:                if (sessionHolder != null && !sessionHolder.isEmpty()) {
295:                    // pre-bound Hibernate Session
296:                    Session session = null;
297:                    if (TransactionSynchronizationManager
298:                            .isSynchronizationActive()
299:                            && sessionHolder.doesNotHoldNonDefaultSession()) {
300:                        // Spring transaction management is active ->
301:                        // register pre-bound Session with it for transactional flushing.
302:                        session = sessionHolder.getValidatedSession();
303:                        if (session != null
304:                                && !sessionHolder
305:                                        .isSynchronizedWithTransaction()) {
306:                            logger
307:                                    .debug("Registering Spring transaction synchronization for existing Hibernate Session");
308:                            TransactionSynchronizationManager
309:                                    .registerSynchronization(new SpringSessionSynchronization(
310:                                            sessionHolder, sessionFactory,
311:                                            jdbcExceptionTranslator, false));
312:                            sessionHolder.setSynchronizedWithTransaction(true);
313:                            // Switch to FlushMode.AUTO, as we have to assume a thread-bound Session
314:                            // with FlushMode.NEVER, which needs to allow flushing within the transaction.
315:                            FlushMode flushMode = session.getFlushMode();
316:                            if (flushMode.lessThan(FlushMode.COMMIT)
317:                                    && !TransactionSynchronizationManager
318:                                            .isCurrentTransactionReadOnly()) {
319:                                session.setFlushMode(FlushMode.AUTO);
320:                                sessionHolder.setPreviousFlushMode(flushMode);
321:                            }
322:                        }
323:                    } else {
324:                        // No Spring transaction management active -> try JTA transaction synchronization.
325:                        session = getJtaSynchronizedSession(sessionHolder,
326:                                sessionFactory, jdbcExceptionTranslator);
327:                    }
328:                    if (session != null) {
329:                        return session;
330:                    }
331:                }
332:
333:                logger.debug("Opening Hibernate Session");
334:                Session session = (entityInterceptor != null ? sessionFactory
335:                        .openSession(entityInterceptor) : sessionFactory
336:                        .openSession());
337:
338:                // Use same Session for further Hibernate actions within the transaction.
339:                // Thread object will get removed by synchronization at transaction completion.
340:                if (TransactionSynchronizationManager.isSynchronizationActive()) {
341:                    // We're within a Spring-managed transaction, possibly from JtaTransactionManager.
342:                    logger
343:                            .debug("Registering Spring transaction synchronization for new Hibernate Session");
344:                    SessionHolder holderToUse = sessionHolder;
345:                    if (holderToUse == null) {
346:                        holderToUse = new SessionHolder(session);
347:                    } else {
348:                        holderToUse.addSession(session);
349:                    }
350:                    if (TransactionSynchronizationManager
351:                            .isCurrentTransactionReadOnly()) {
352:                        session.setFlushMode(FlushMode.NEVER);
353:                    }
354:                    TransactionSynchronizationManager
355:                            .registerSynchronization(new SpringSessionSynchronization(
356:                                    holderToUse, sessionFactory,
357:                                    jdbcExceptionTranslator, true));
358:                    holderToUse.setSynchronizedWithTransaction(true);
359:                    if (holderToUse != sessionHolder) {
360:                        TransactionSynchronizationManager.bindResource(
361:                                sessionFactory, holderToUse);
362:                    }
363:                } else {
364:                    // No Spring transaction management active -> try JTA transaction synchronization.
365:                    registerJtaSynchronization(session, sessionFactory,
366:                            jdbcExceptionTranslator, sessionHolder);
367:                }
368:
369:                // Check whether we are allowed to return the Session.
370:                if (!allowCreate
371:                        && !isSessionTransactional(session, sessionFactory)) {
372:                    closeSession(session);
373:                    throw new IllegalStateException(
374:                            "No Hibernate Session bound to thread, "
375:                                    + "and configuration does not allow creation of non-transactional one here");
376:                }
377:
378:                return session;
379:            }
380:
381:            /**
382:             * Retrieve a Session from the given SessionHolder, potentially from a
383:             * JTA transaction synchronization.
384:             * @param sessionHolder the SessionHolder to check
385:             * @param sessionFactory the SessionFactory to get the JTA TransactionManager from
386:             * @param jdbcExceptionTranslator SQLExcepionTranslator to use for flushing the
387:             * Session on transaction synchronization (may be <code>null</code>)
388:             * @return the associated Session, if any
389:             * @throws DataAccessResourceFailureException if the Session couldn't be created
390:             */
391:            private static Session getJtaSynchronizedSession(
392:                    SessionHolder sessionHolder, SessionFactory sessionFactory,
393:                    SQLExceptionTranslator jdbcExceptionTranslator)
394:                    throws DataAccessResourceFailureException {
395:
396:                // JTA synchronization is only possible with a javax.transaction.TransactionManager.
397:                // We'll check the Hibernate SessionFactory: If a TransactionManagerLookup is specified
398:                // in Hibernate configuration, it will contain a TransactionManager reference.
399:                TransactionManager jtaTm = getJtaTransactionManager(
400:                        sessionFactory, sessionHolder.getAnySession());
401:                if (jtaTm != null) {
402:                    // Check whether JTA transaction management is active ->
403:                    // fetch pre-bound Session for the current JTA transaction, if any.
404:                    // (just necessary for JTA transaction suspension, with an individual
405:                    // Hibernate Session per currently active/suspended transaction)
406:                    try {
407:                        // Look for transaction-specific Session.
408:                        Transaction jtaTx = jtaTm.getTransaction();
409:                        if (jtaTx != null) {
410:                            int jtaStatus = jtaTx.getStatus();
411:                            if (jtaStatus == Status.STATUS_ACTIVE
412:                                    || jtaStatus == Status.STATUS_MARKED_ROLLBACK) {
413:                                Session session = sessionHolder
414:                                        .getValidatedSession(jtaTx);
415:                                if (session == null
416:                                        && !sessionHolder
417:                                                .isSynchronizedWithTransaction()) {
418:                                    // No transaction-specific Session found: If not already marked as
419:                                    // synchronized with transaction, register the default thread-bound
420:                                    // Session as JTA-transactional. If there is no default Session,
421:                                    // we're a new inner JTA transaction with an outer one being suspended:
422:                                    // In that case, we'll return null to trigger opening of a new Session.
423:                                    session = sessionHolder
424:                                            .getValidatedSession();
425:                                    if (session != null) {
426:                                        logger
427:                                                .debug("Registering JTA transaction synchronization for existing Hibernate Session");
428:                                        sessionHolder
429:                                                .addSession(jtaTx, session);
430:                                        jtaTx
431:                                                .registerSynchronization(new SpringJtaSynchronizationAdapter(
432:                                                        new SpringSessionSynchronization(
433:                                                                sessionHolder,
434:                                                                sessionFactory,
435:                                                                jdbcExceptionTranslator,
436:                                                                false), jtaTm));
437:                                        sessionHolder
438:                                                .setSynchronizedWithTransaction(true);
439:                                        // Switch to FlushMode.AUTO, as we have to assume a thread-bound Session
440:                                        // with FlushMode.NEVER, which needs to allow flushing within the transaction.
441:                                        FlushMode flushMode = session
442:                                                .getFlushMode();
443:                                        if (flushMode
444:                                                .lessThan(FlushMode.COMMIT)) {
445:                                            session
446:                                                    .setFlushMode(FlushMode.AUTO);
447:                                            sessionHolder
448:                                                    .setPreviousFlushMode(flushMode);
449:                                        }
450:                                    }
451:                                }
452:                                return session;
453:                            }
454:                        }
455:                        // No transaction active -> simply return default thread-bound Session, if any
456:                        // (possibly from OpenSessionInViewFilter/Interceptor).
457:                        return sessionHolder.getValidatedSession();
458:                    } catch (Throwable ex) {
459:                        throw new DataAccessResourceFailureException(
460:                                "Could not check JTA transaction", ex);
461:                    }
462:                } else {
463:                    // No JTA TransactionManager -> simply return default thread-bound Session, if any
464:                    // (possibly from OpenSessionInViewFilter/Interceptor).
465:                    return sessionHolder.getValidatedSession();
466:                }
467:            }
468:
469:            /**
470:             * Register a JTA synchronization for the given Session, if any.
471:             * @param sessionHolder the existing thread-bound SessionHolder, if any
472:             * @param session the Session to register
473:             * @param sessionFactory the SessionFactory that the Session was created with
474:             * @param jdbcExceptionTranslator SQLExcepionTranslator to use for flushing the
475:             * Session on transaction synchronization (may be <code>null</code>)
476:             */
477:            private static void registerJtaSynchronization(Session session,
478:                    SessionFactory sessionFactory,
479:                    SQLExceptionTranslator jdbcExceptionTranslator,
480:                    SessionHolder sessionHolder) {
481:
482:                // JTA synchronization is only possible with a javax.transaction.TransactionManager.
483:                // We'll check the Hibernate SessionFactory: If a TransactionManagerLookup is specified
484:                // in Hibernate configuration, it will contain a TransactionManager reference.
485:                TransactionManager jtaTm = getJtaTransactionManager(
486:                        sessionFactory, session);
487:                if (jtaTm != null) {
488:                    try {
489:                        Transaction jtaTx = jtaTm.getTransaction();
490:                        if (jtaTx != null) {
491:                            int jtaStatus = jtaTx.getStatus();
492:                            if (jtaStatus == Status.STATUS_ACTIVE
493:                                    || jtaStatus == Status.STATUS_MARKED_ROLLBACK) {
494:                                logger
495:                                        .debug("Registering JTA transaction synchronization for new Hibernate Session");
496:                                SessionHolder holderToUse = sessionHolder;
497:                                // Register JTA Transaction with existing SessionHolder.
498:                                // Create a new SessionHolder if none existed before.
499:                                if (holderToUse == null) {
500:                                    holderToUse = new SessionHolder(jtaTx,
501:                                            session);
502:                                } else {
503:                                    holderToUse.addSession(jtaTx, session);
504:                                }
505:                                jtaTx
506:                                        .registerSynchronization(new SpringJtaSynchronizationAdapter(
507:                                                new SpringSessionSynchronization(
508:                                                        holderToUse,
509:                                                        sessionFactory,
510:                                                        jdbcExceptionTranslator,
511:                                                        true), jtaTm));
512:                                holderToUse
513:                                        .setSynchronizedWithTransaction(true);
514:                                if (holderToUse != sessionHolder) {
515:                                    TransactionSynchronizationManager
516:                                            .bindResource(sessionFactory,
517:                                                    holderToUse);
518:                                }
519:                            }
520:                        }
521:                    } catch (Throwable ex) {
522:                        throw new DataAccessResourceFailureException(
523:                                "Could not register synchronization with JTA TransactionManager",
524:                                ex);
525:                    }
526:                }
527:            }
528:
529:            /**
530:             * Get a new Hibernate Session from the given SessionFactory.
531:             * Will return a new Session even if there already is a pre-bound
532:             * Session for the given SessionFactory.
533:             * <p>Within a transaction, this method will create a new Session
534:             * that shares the transaction's JDBC Connection. More specifically,
535:             * it will use the same JDBC Connection as the pre-bound Hibernate Session.
536:             * @param sessionFactory Hibernate SessionFactory to create the session with
537:             * @return the new Session
538:             */
539:            public static Session getNewSession(SessionFactory sessionFactory) {
540:                return getNewSession(sessionFactory, null);
541:            }
542:
543:            /**
544:             * Get a new Hibernate Session from the given SessionFactory.
545:             * Will return a new Session even if there already is a pre-bound
546:             * Session for the given SessionFactory.
547:             * <p>Within a transaction, this method will create a new Session
548:             * that shares the transaction's JDBC Connection. More specifically,
549:             * it will use the same JDBC Connection as the pre-bound Hibernate Session.
550:             * @param sessionFactory Hibernate SessionFactory to create the session with
551:             * @param entityInterceptor Hibernate entity interceptor, or <code>null</code> if none
552:             * @return the new Session
553:             */
554:            public static Session getNewSession(SessionFactory sessionFactory,
555:                    Interceptor entityInterceptor) {
556:                Assert.notNull(sessionFactory, "No SessionFactory specified");
557:
558:                try {
559:                    SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager
560:                            .getResource(sessionFactory);
561:                    if (sessionHolder != null && !sessionHolder.isEmpty()) {
562:                        if (entityInterceptor != null) {
563:                            return sessionFactory.openSession(sessionHolder
564:                                    .getAnySession().connection(),
565:                                    entityInterceptor);
566:                        } else {
567:                            return sessionFactory.openSession(sessionHolder
568:                                    .getAnySession().connection());
569:                        }
570:                    } else {
571:                        if (entityInterceptor != null) {
572:                            return sessionFactory
573:                                    .openSession(entityInterceptor);
574:                        } else {
575:                            return sessionFactory.openSession();
576:                        }
577:                    }
578:                } catch (HibernateException ex) {
579:                    throw new DataAccessResourceFailureException(
580:                            "Could not open Hibernate Session", ex);
581:                }
582:            }
583:
584:            /**
585:             * Stringify the given Session for debug logging.
586:             * Returns output equivalent to <code>Object.toString()</code>:
587:             * the fully qualified class name + "@" + the identity hash code.
588:             * <p>The only reason why this is necessary is because Hibernate3's
589:             * <code>Session.toString()</code> implementation is broken (and won't be fixed):
590:             * it logs the toString representation of all persistent objects in the Session,
591:             * which might lead to ConcurrentModificationExceptions if the persistent objects
592:             * in turn refer to the Session (for example, for lazy loading).
593:             * @param session the Hibernate Session to stringify
594:             * @return the String representation of the given Session
595:             */
596:            public static String toString(Session session) {
597:                return session.getClass().getName() + "@"
598:                        + Integer.toHexString(System.identityHashCode(session));
599:            }
600:
601:            /**
602:             * Return whether the given Hibernate Session is transactional, that is,
603:             * bound to the current thread by Spring's transaction facilities.
604:             * @param session the Hibernate Session to check
605:             * @param sessionFactory Hibernate SessionFactory that the Session was created with
606:             * (may be <code>null</code>)
607:             * @return whether the Session is transactional
608:             */
609:            public static boolean isSessionTransactional(Session session,
610:                    SessionFactory sessionFactory) {
611:                if (sessionFactory == null) {
612:                    return false;
613:                }
614:                SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager
615:                        .getResource(sessionFactory);
616:                return (sessionHolder != null && sessionHolder
617:                        .containsSession(session));
618:            }
619:
620:            /**
621:             * Apply the current transaction timeout, if any, to the given
622:             * Hibernate Query object.
623:             * @param query the Hibernate Query object
624:             * @param sessionFactory Hibernate SessionFactory that the Query was created for
625:             * (may be <code>null</code>)
626:             * @see org.hibernate.Query#setTimeout
627:             */
628:            public static void applyTransactionTimeout(Query query,
629:                    SessionFactory sessionFactory) {
630:                Assert.notNull(query, "No Query object specified");
631:                if (sessionFactory != null) {
632:                    SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager
633:                            .getResource(sessionFactory);
634:                    if (sessionHolder != null && sessionHolder.hasTimeout()) {
635:                        query
636:                                .setTimeout(sessionHolder
637:                                        .getTimeToLiveInSeconds());
638:                    }
639:                }
640:            }
641:
642:            /**
643:             * Apply the current transaction timeout, if any, to the given
644:             * Hibernate Criteria object.
645:             * @param criteria the Hibernate Criteria object
646:             * @param sessionFactory Hibernate SessionFactory that the Criteria was created for
647:             * @see org.hibernate.Criteria#setTimeout
648:             */
649:            public static void applyTransactionTimeout(Criteria criteria,
650:                    SessionFactory sessionFactory) {
651:                Assert.notNull(criteria, "No Criteria object specified");
652:                SessionHolder sessionHolder = (SessionHolder) TransactionSynchronizationManager
653:                        .getResource(sessionFactory);
654:                if (sessionHolder != null && sessionHolder.hasTimeout()) {
655:                    criteria.setTimeout(sessionHolder.getTimeToLiveInSeconds());
656:                }
657:            }
658:
659:            /**
660:             * Convert the given HibernateException to an appropriate exception
661:             * from the <code>org.springframework.dao</code> hierarchy.
662:             * @param ex HibernateException that occured
663:             * @return the corresponding DataAccessException instance
664:             * @see HibernateAccessor#convertHibernateAccessException
665:             * @see HibernateTransactionManager#convertHibernateAccessException
666:             */
667:            public static DataAccessException convertHibernateAccessException(
668:                    HibernateException ex) {
669:                if (ex instanceof  JDBCConnectionException) {
670:                    return new DataAccessResourceFailureException(ex
671:                            .getMessage(), ex);
672:                }
673:                if (ex instanceof  SQLGrammarException) {
674:                    return new InvalidDataAccessResourceUsageException(ex
675:                            .getMessage(), ex);
676:                }
677:                if (ex instanceof  DataException) {
678:                    return new InvalidDataAccessResourceUsageException(ex
679:                            .getMessage(), ex);
680:                }
681:                if (ex instanceof  LockAcquisitionException) {
682:                    return new CannotAcquireLockException(ex.getMessage(), ex);
683:                }
684:                if (ex instanceof  ConstraintViolationException) {
685:                    return new DataIntegrityViolationException(ex.getMessage(),
686:                            ex);
687:                }
688:                if (ex instanceof  JDBCException) {
689:                    return new HibernateJdbcException((JDBCException) ex);
690:                }
691:                if (ex instanceof  PropertyValueException) {
692:                    return new DataIntegrityViolationException(ex.getMessage(),
693:                            ex);
694:                }
695:                if (ex instanceof  PersistentObjectException) {
696:                    return new InvalidDataAccessApiUsageException(ex
697:                            .getMessage(), ex);
698:                }
699:                if (ex instanceof  TransientObjectException) {
700:                    return new InvalidDataAccessApiUsageException(ex
701:                            .getMessage(), ex);
702:                }
703:                if (ex instanceof  ObjectDeletedException) {
704:                    return new InvalidDataAccessApiUsageException(ex
705:                            .getMessage(), ex);
706:                }
707:                if (ex instanceof  QueryException) {
708:                    return new HibernateQueryException((QueryException) ex);
709:                }
710:                if (ex instanceof  UnresolvableObjectException) {
711:                    return new HibernateObjectRetrievalFailureException(
712:                            (UnresolvableObjectException) ex);
713:                }
714:                if (ex instanceof  WrongClassException) {
715:                    return new HibernateObjectRetrievalFailureException(
716:                            (WrongClassException) ex);
717:                }
718:                if (ex instanceof  NonUniqueResultException) {
719:                    return new IncorrectResultSizeDataAccessException(ex
720:                            .getMessage(), 1);
721:                }
722:                if (ex instanceof  StaleObjectStateException) {
723:                    return new HibernateOptimisticLockingFailureException(
724:                            (StaleObjectStateException) ex);
725:                }
726:                if (ex instanceof  StaleStateException) {
727:                    return new HibernateOptimisticLockingFailureException(
728:                            (StaleStateException) ex);
729:                }
730:
731:                // fallback
732:                return new HibernateSystemException(ex);
733:            }
734:
735:            /**
736:             * Determine whether deferred close is active for the current thread
737:             * and the given SessionFactory.
738:             * @param sessionFactory the Hibernate SessionFactory to check
739:             * @return whether deferred close is active
740:             */
741:            public static boolean isDeferredCloseActive(
742:                    SessionFactory sessionFactory) {
743:                Assert.notNull(sessionFactory, "No SessionFactory specified");
744:                Map holderMap = (Map) deferredCloseHolder.get();
745:                return (holderMap != null && holderMap
746:                        .containsKey(sessionFactory));
747:            }
748:
749:            /**
750:             * Initialize deferred close for the current thread and the given SessionFactory.
751:             * Sessions will not be actually closed on close calls then, but rather at a
752:             * {@link #processDeferredClose} call at a finishing point (like request completion).
753:             * <p>Used by {@link org.springframework.orm.hibernate3.support.OpenSessionInViewFilter}
754:             * and {@link org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor}
755:             * when not configured for a single session.
756:             * @param sessionFactory the Hibernate SessionFactory to initialize deferred close for
757:             * @see #processDeferredClose
758:             * @see #releaseSession
759:             * @see org.springframework.orm.hibernate3.support.OpenSessionInViewFilter#setSingleSession
760:             * @see org.springframework.orm.hibernate3.support.OpenSessionInViewInterceptor#setSingleSession
761:             */
762:            public static void initDeferredClose(SessionFactory sessionFactory) {
763:                Assert.notNull(sessionFactory, "No SessionFactory specified");
764:                logger
765:                        .debug("Initializing deferred close of Hibernate Sessions");
766:                Map holderMap = (Map) deferredCloseHolder.get();
767:                if (holderMap == null) {
768:                    holderMap = new HashMap();
769:                    deferredCloseHolder.set(holderMap);
770:                }
771:                holderMap.put(sessionFactory, new LinkedHashSet(4));
772:            }
773:
774:            /**
775:             * Process all Hibernate Sessions that have been registered for deferred close
776:             * for the given SessionFactory.
777:             * @param sessionFactory the Hibernate SessionFactory to process deferred close for
778:             * @see #initDeferredClose
779:             * @see #releaseSession
780:             */
781:            public static void processDeferredClose(
782:                    SessionFactory sessionFactory) {
783:                Assert.notNull(sessionFactory, "No SessionFactory specified");
784:
785:                Map holderMap = (Map) deferredCloseHolder.get();
786:                if (holderMap == null || !holderMap.containsKey(sessionFactory)) {
787:                    throw new IllegalStateException(
788:                            "Deferred close not active for SessionFactory ["
789:                                    + sessionFactory + "]");
790:                }
791:
792:                logger.debug("Processing deferred close of Hibernate Sessions");
793:                Set sessions = (Set) holderMap.remove(sessionFactory);
794:                for (Iterator it = sessions.iterator(); it.hasNext();) {
795:                    closeSession((Session) it.next());
796:                }
797:
798:                if (holderMap.isEmpty()) {
799:                    deferredCloseHolder.set(null);
800:                }
801:            }
802:
803:            /**
804:             * Close the given Session, created via the given factory,
805:             * if it is not managed externally (i.e. not bound to the thread).
806:             * @param session the Hibernate Session to close (may be <code>null</code>)
807:             * @param sessionFactory Hibernate SessionFactory that the Session was created with
808:             * (may be <code>null</code>)
809:             */
810:            public static void releaseSession(Session session,
811:                    SessionFactory sessionFactory) {
812:                if (session == null) {
813:                    return;
814:                }
815:                // Only close non-transactional Sessions.
816:                if (!isSessionTransactional(session, sessionFactory)) {
817:                    closeSessionOrRegisterDeferredClose(session, sessionFactory);
818:                }
819:            }
820:
821:            /**
822:             * Close the given Session or register it for deferred close.
823:             * @param session the Hibernate Session to close
824:             * @param sessionFactory Hibernate SessionFactory that the Session was created with
825:             * (may be <code>null</code>)
826:             * @see #initDeferredClose
827:             * @see #processDeferredClose
828:             */
829:            static void closeSessionOrRegisterDeferredClose(Session session,
830:                    SessionFactory sessionFactory) {
831:                Map holderMap = (Map) deferredCloseHolder.get();
832:                if (holderMap != null && sessionFactory != null
833:                        && holderMap.containsKey(sessionFactory)) {
834:                    logger
835:                            .debug("Registering Hibernate Session for deferred close");
836:                    // Switch Session to FlushMode.NEVER for remaining lifetime.
837:                    session.setFlushMode(FlushMode.NEVER);
838:                    Set sessions = (Set) holderMap.get(sessionFactory);
839:                    sessions.add(session);
840:                } else {
841:                    closeSession(session);
842:                }
843:            }
844:
845:            /**
846:             * Perform actual closing of the Hibernate Session,
847:             * catching and logging any cleanup exceptions thrown.
848:             * @param session the Hibernate Session to close (may be <code>null</code>)
849:             * @see org.hibernate.Session#close()
850:             */
851:            public static void closeSession(Session session) {
852:                if (session != null) {
853:                    logger.debug("Closing Hibernate Session");
854:                    try {
855:                        session.close();
856:                    } catch (HibernateException ex) {
857:                        logger.debug("Could not close Hibernate Session", ex);
858:                    } catch (Throwable ex) {
859:                        logger
860:                                .debug(
861:                                        "Unexpected exception on closing Hibernate Session",
862:                                        ex);
863:                    }
864:                }
865:            }
866:
867:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.