View Javadoc
1   /*
2    * Copyright 2002-2012 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.util.Map;
20  import java.util.concurrent.ConcurrentHashMap;
21  
22  import org.hibernate.FlushMode;
23  import org.hibernate.Session;
24  import org.hibernate.Transaction;
25  
26  import org.springframework.transaction.support.ResourceHolderSupport;
27  import org.springframework.util.Assert;
28  
29  /**
30   * Session holder, wrapping a Hibernate Session and a Hibernate Transaction.
31   * HibernateTransactionManager binds instances of this class to the thread,
32   * for a given SessionFactory.
33   *
34   * <p>Note: This is an SPI class, not intended to be used by applications.
35   *
36   * @author Juergen Hoeller
37   * @since 1.2
38   * @see HibernateTransactionManager
39   * @see SessionFactoryUtils
40   */
41  public class SessionHolder extends ResourceHolderSupport {
42  
43  	private static final Object DEFAULT_KEY = new Object();
44  
45  	/**
46  	 * This Map needs to be concurrent because there might be multi-threaded
47  	 * access in the case of JTA with remote transaction propagation.
48  	 */
49  	private final Map<Object, Session> sessionMap = new ConcurrentHashMap<Object, Session>(1);
50  
51  	private Transaction transaction;
52  
53  	private FlushMode previousFlushMode;
54  
55  
56  	public SessionHolder(Session session) {
57  		addSession(session);
58  	}
59  
60  	public SessionHolder(Object key, Session session) {
61  		addSession(key, session);
62  	}
63  
64  
65  	public Session getSession() {
66  		return getSession(DEFAULT_KEY);
67  	}
68  
69  	public Session getSession(Object key) {
70  		return this.sessionMap.get(key);
71  	}
72  
73  	public Session getValidatedSession() {
74  		return getValidatedSession(DEFAULT_KEY);
75  	}
76  
77  	public Session getValidatedSession(Object key) {
78  		Session session = this.sessionMap.get(key);
79  		// Check for dangling Session that's around but already closed.
80  		// Effectively an assertion: that should never happen in practice.
81  		// We'll seamlessly remove the Session here, to not let it cause
82  		// any side effects.
83  		if (session != null && !session.isOpen()) {
84  			this.sessionMap.remove(key);
85  			session = null;
86  		}
87  		return session;
88  	}
89  
90  	public Session getAnySession() {
91  		if (!this.sessionMap.isEmpty()) {
92  			return this.sessionMap.values().iterator().next();
93  		}
94  		return null;
95  	}
96  
97  	public void addSession(Session session) {
98  		addSession(DEFAULT_KEY, session);
99  	}
100 
101 	public void addSession(Object key, Session session) {
102 		Assert.notNull(key, "Key must not be null");
103 		Assert.notNull(session, "Session must not be null");
104 		this.sessionMap.put(key, session);
105 	}
106 
107 	public Session removeSession(Object key) {
108 		return this.sessionMap.remove(key);
109 	}
110 
111 	public boolean containsSession(Session session) {
112 		return this.sessionMap.containsValue(session);
113 	}
114 
115 	public boolean isEmpty() {
116 		return this.sessionMap.isEmpty();
117 	}
118 
119 	public boolean doesNotHoldNonDefaultSession() {
120 		return this.sessionMap.isEmpty() ||
121 				(this.sessionMap.size() == 1 && this.sessionMap.containsKey(DEFAULT_KEY));
122 	}
123 
124 
125 	public void setTransaction(Transaction transaction) {
126 		this.transaction = transaction;
127 	}
128 
129 	public Transaction getTransaction() {
130 		return this.transaction;
131 	}
132 
133 	public void setPreviousFlushMode(FlushMode previousFlushMode) {
134 		this.previousFlushMode = previousFlushMode;
135 	}
136 
137 	public FlushMode getPreviousFlushMode() {
138 		return this.previousFlushMode;
139 	}
140 
141 
142 	@Override
143 	public void clear() {
144 		super.clear();
145 		this.transaction = null;
146 		this.previousFlushMode = null;
147 	}
148 
149 }