1 /*
2  * Copyright 2002-2011 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.hibernate4;
18 
19 import javax.transaction.TransactionManager;
20 
21 import org.hibernate.FlushMode;
22 import org.hibernate.HibernateException;
23 import org.hibernate.Session;
24 import org.hibernate.context.spi.CurrentSessionContext;
25 import org.hibernate.engine.spi.SessionFactoryImplementor;
26 import org.hibernate.service.jta.platform.spi.JtaPlatform;
27 
28 import org.springframework.transaction.support.TransactionSynchronizationManager;
29 
30 /**
31  * Implementation of Hibernate 3.1's CurrentSessionContext interface
32  * that delegates to Spring's SessionFactoryUtils for providing a
33  * Spring-managed current Session.
34  *
35  * <p>This CurrentSessionContext implementation can also be specified in custom
36  * SessionFactory setup through the "hibernate.current_session_context_class"
37  * property, with the fully qualified name of this class as value.
38  *
39  * @author Juergen Hoeller
40  * @since 3.1
41  */
42 @SuppressWarnings("serial")
43 public class SpringSessionContext implements CurrentSessionContext {
44 
45 	private final SessionFactoryImplementor sessionFactory;
46 
47 	private final CurrentSessionContext jtaSessionContext;
48 
49 
50 	/**
51 	 * Create a new SpringSessionContext for the given Hibernate SessionFactory.
52 	 * @param sessionFactory the SessionFactory to provide current Sessions for
53 	 */
SpringSessionContext(SessionFactoryImplementor sessionFactory)54 	public SpringSessionContext(SessionFactoryImplementor sessionFactory) {
55 		this.sessionFactory = sessionFactory;
56 		JtaPlatform jtaPlatform = sessionFactory.getServiceRegistry().getService(JtaPlatform.class);
57 		TransactionManager transactionManager = jtaPlatform.retrieveTransactionManager();
58 		this.jtaSessionContext = (transactionManager != null ? new SpringJtaSessionContext(sessionFactory) : null);
59 	}
60 
61 
62 	/**
63 	 * Retrieve the Spring-managed Session for the current thread, if any.
64 	 */
currentSession()65 	public Session currentSession() throws HibernateException {
66 		Object value = TransactionSynchronizationManager.getResource(this.sessionFactory);
67 		if (value instanceof Session) {
68 			return (Session) value;
69 		}
70 		else if (value instanceof SessionHolder) {
71 			SessionHolder sessionHolder = (SessionHolder) value;
72 			Session session = sessionHolder.getSession();
73 			if (TransactionSynchronizationManager.isSynchronizationActive() &&
74 					!sessionHolder.isSynchronizedWithTransaction()) {
75 				TransactionSynchronizationManager.registerSynchronization(
76 						new SpringSessionSynchronization(sessionHolder, this.sessionFactory));
77 				sessionHolder.setSynchronizedWithTransaction(true);
78 				// Switch to FlushMode.AUTO, as we have to assume a thread-bound Session
79 				// with FlushMode.MANUAL, which needs to allow flushing within the transaction.
80 				FlushMode flushMode = session.getFlushMode();
81 				if (FlushMode.isManualFlushMode(flushMode) &&
82 						!TransactionSynchronizationManager.isCurrentTransactionReadOnly()) {
83 					session.setFlushMode(FlushMode.AUTO);
84 					sessionHolder.setPreviousFlushMode(flushMode);
85 				}
86 			}
87 			return session;
88 		}
89 		else if (this.jtaSessionContext != null) {
90 			Session session = this.jtaSessionContext.currentSession();
91 			if (TransactionSynchronizationManager.isSynchronizationActive()) {
92 				TransactionSynchronizationManager.registerSynchronization(new SpringFlushSynchronization(session));
93 			}
94 			return session;
95 		}
96 		else {
97 			throw new HibernateException("No Session found for current thread");
98 		}
99 	}
100 
101 }
102