1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.springframework.orm.hibernate3;
18
19 import javax.transaction.SystemException;
20 import javax.transaction.Transaction;
21 import javax.transaction.TransactionManager;
22
23 import org.hibernate.FlushMode;
24 import org.hibernate.HibernateException;
25 import org.hibernate.JDBCException;
26 import org.hibernate.Session;
27 import org.hibernate.SessionFactory;
28 import org.hibernate.engine.SessionImplementor;
29
30 import org.springframework.core.Ordered;
31 import org.springframework.dao.DataAccessException;
32 import org.springframework.dao.DataAccessResourceFailureException;
33 import org.springframework.jdbc.support.SQLExceptionTranslator;
34 import org.springframework.transaction.support.TransactionSynchronization;
35 import org.springframework.transaction.support.TransactionSynchronizationManager;
36
37
38
39
40
41
42
43
44
45
46 class SpringSessionSynchronization implements TransactionSynchronization, Ordered {
47
48 private final SessionHolder sessionHolder;
49
50 private final SessionFactory sessionFactory;
51
52 private final SQLExceptionTranslator jdbcExceptionTranslator;
53
54 private final boolean newSession;
55
56
57
58
59
60 private boolean hibernateTransactionCompletion = false;
61
62 private Transaction jtaTransaction;
63
64 private boolean holderActive = true;
65
66
67 public SpringSessionSynchronization(
68 SessionHolder sessionHolder, SessionFactory sessionFactory,
69 SQLExceptionTranslator jdbcExceptionTranslator, boolean newSession) {
70
71 this.sessionHolder = sessionHolder;
72 this.sessionFactory = sessionFactory;
73 this.jdbcExceptionTranslator = jdbcExceptionTranslator;
74 this.newSession = newSession;
75
76
77 TransactionManager jtaTm =
78 SessionFactoryUtils.getJtaTransactionManager(sessionFactory, sessionHolder.getAnySession());
79 if (jtaTm != null) {
80 this.hibernateTransactionCompletion = true;
81
82
83
84 try {
85 this.jtaTransaction = jtaTm.getTransaction();
86 }
87 catch (SystemException ex) {
88 throw new DataAccessResourceFailureException("Could not access JTA transaction", ex);
89 }
90 }
91 }
92
93
94
95
96
97 private Session getCurrentSession() {
98 Session session = null;
99 if (this.jtaTransaction != null) {
100 session = this.sessionHolder.getSession(this.jtaTransaction);
101 }
102 if (session == null) {
103 session = this.sessionHolder.getSession();
104 }
105 return session;
106 }
107
108
109 @Override
110 public int getOrder() {
111 return SessionFactoryUtils.SESSION_SYNCHRONIZATION_ORDER;
112 }
113
114 @Override
115 public void suspend() {
116 if (this.holderActive) {
117 TransactionSynchronizationManager.unbindResource(this.sessionFactory);
118
119 getCurrentSession().disconnect();
120 }
121 }
122
123 @Override
124 public void resume() {
125 if (this.holderActive) {
126 TransactionSynchronizationManager.bindResource(this.sessionFactory, this.sessionHolder);
127 }
128 }
129
130 @Override
131 public void flush() {
132 try {
133 SessionFactoryUtils.logger.debug("Flushing Hibernate Session on explicit request");
134 getCurrentSession().flush();
135 }
136 catch (HibernateException ex) {
137 throw translateException(ex);
138 }
139 }
140
141 @Override
142 public void beforeCommit(boolean readOnly) throws DataAccessException {
143 if (!readOnly) {
144 Session session = getCurrentSession();
145
146
147 if (!session.getFlushMode().lessThan(FlushMode.COMMIT)) {
148 try {
149 SessionFactoryUtils.logger.debug("Flushing Hibernate Session on transaction synchronization");
150 session.flush();
151 }
152 catch (HibernateException ex) {
153 throw translateException(ex);
154 }
155 }
156 }
157 }
158
159 private DataAccessException translateException(HibernateException ex) {
160 if (this.jdbcExceptionTranslator != null && ex instanceof JDBCException) {
161 JDBCException jdbcEx = (JDBCException) ex;
162 return this.jdbcExceptionTranslator.translate(
163 "Hibernate flushing: " + jdbcEx.getMessage(), jdbcEx.getSQL(), jdbcEx.getSQLException());
164 }
165 return SessionFactoryUtils.convertHibernateAccessException(ex);
166 }
167
168 @Override
169 public void beforeCompletion() {
170 if (this.jtaTransaction != null) {
171
172
173 Session session = this.sessionHolder.removeSession(this.jtaTransaction);
174 if (session != null) {
175 if (this.sessionHolder.isEmpty()) {
176
177 TransactionSynchronizationManager.unbindResourceIfPossible(this.sessionFactory);
178 this.holderActive = false;
179 }
180
181
182 if (session != this.sessionHolder.getSession()) {
183 SessionFactoryUtils.closeSessionOrRegisterDeferredClose(session, this.sessionFactory);
184 }
185 else {
186 if (this.sessionHolder.getPreviousFlushMode() != null) {
187
188 session.setFlushMode(this.sessionHolder.getPreviousFlushMode());
189 }
190
191 session.disconnect();
192 }
193 return;
194 }
195 }
196
197 if (this.newSession) {
198
199 TransactionSynchronizationManager.unbindResource(this.sessionFactory);
200 this.holderActive = false;
201 if (this.hibernateTransactionCompletion) {
202
203
204
205
206 SessionFactoryUtils.closeSessionOrRegisterDeferredClose(this.sessionHolder.getSession(), this.sessionFactory);
207 }
208 }
209 else {
210 Session session = this.sessionHolder.getSession();
211 if (this.sessionHolder.getPreviousFlushMode() != null) {
212
213 session.setFlushMode(this.sessionHolder.getPreviousFlushMode());
214 }
215 if (this.hibernateTransactionCompletion) {
216
217
218 session.disconnect();
219 }
220 }
221 }
222
223 @Override
224 public void afterCommit() {
225 }
226
227 @Override
228 public void afterCompletion(int status) {
229 try {
230 if (!this.hibernateTransactionCompletion || !this.newSession) {
231
232
233
234 Session session = this.sessionHolder.getSession();
235
236
237 try {
238 if (session instanceof SessionImplementor) {
239 ((SessionImplementor) session).afterTransactionCompletion(status == STATUS_COMMITTED, null);
240 }
241 }
242 finally {
243
244
245 if (this.newSession) {
246 SessionFactoryUtils.closeSessionOrRegisterDeferredClose(session, this.sessionFactory);
247 }
248 else if (!this.hibernateTransactionCompletion) {
249 session.disconnect();
250 }
251 }
252 }
253 if (!this.newSession && status != STATUS_COMMITTED) {
254
255
256 this.sessionHolder.getSession().clear();
257 }
258 }
259 finally {
260 if (this.sessionHolder.doesNotHoldNonDefaultSession()) {
261 this.sessionHolder.setSynchronizedWithTransaction(false);
262 }
263 }
264 }
265
266 }