Source Code Cross Referenced for DataSourceTransactionManager.java in  » J2EE » spring-framework-2.5 » org » springframework » jdbc » datasource » 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.jdbc.datasource 
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.jdbc.datasource;
018:
019:        import java.sql.Connection;
020:        import java.sql.SQLException;
021:
022:        import javax.sql.DataSource;
023:
024:        import org.springframework.beans.factory.InitializingBean;
025:        import org.springframework.transaction.CannotCreateTransactionException;
026:        import org.springframework.transaction.TransactionDefinition;
027:        import org.springframework.transaction.TransactionSystemException;
028:        import org.springframework.transaction.support.AbstractPlatformTransactionManager;
029:        import org.springframework.transaction.support.DefaultTransactionStatus;
030:        import org.springframework.transaction.support.ResourceTransactionManager;
031:        import org.springframework.transaction.support.TransactionSynchronizationManager;
032:
033:        /**
034:         * {@link org.springframework.transaction.PlatformTransactionManager}
035:         * implementation for a single JDBC {@link javax.sql.DataSource}. This class is
036:         * capable of working in any environment with any JDBC driver, as long as the setup
037:         * uses a JDBC 2.0 Standard Extensions / JDBC 3.0 <code>javax.sql.DataSource</code>
038:         * as its Connection factory mechanism. Binds a JDBC Connection from the specified
039:         * DataSource to the current thread, potentially allowing for one thread-bound
040:         * Connection per DataSource.
041:         *
042:         * <p><b>Note: The DataSource that this transaction manager operates on needs
043:         * to return independent Connections.</b> The Connections may come from a pool
044:         * (the typical case), but the DataSource must not return thread-scoped /
045:         * request-scoped Connections or the like. This transaction manager will
046:         * associate Connections with thread-bound transactions itself, according
047:         * to the specified propagation behavior. It assumes that a separate,
048:         * independent Connection can be obtained even during an ongoing transaction.
049:         *
050:         * <p>Application code is required to retrieve the JDBC Connection via
051:         * {@link DataSourceUtils#getConnection(DataSource)} instead of a standard
052:         * J2EE-style {@link DataSource#getConnection()} call. Spring classes such as
053:         * {@link org.springframework.jdbc.core.JdbcTemplate} use this strategy implicitly.
054:         * If not used in combination with this transaction manager, the
055:         * {@link DataSourceUtils} lookup strategy behaves exactly like the native
056:         * DataSource lookup; it can thus be used in a portable fashion.
057:         *
058:         * <p>Alternatively, you can allow application code to work with the standard
059:         * J2EE-style lookup pattern {@link DataSource#getConnection()}, for example for
060:         * legacy code that is not aware of Spring at all. In that case, define a
061:         * {@link TransactionAwareDataSourceProxy} for your target DataSource, and pass
062:         * that proxy DataSource to your DAOs, which will automatically participate in
063:         * Spring-managed transactions when accessing it.
064:         *
065:         * <p>Supports custom isolation levels, and timeouts which get applied as
066:         * appropriate JDBC statement timeouts. To support the latter, application code
067:         * must either use {@link org.springframework.jdbc.core.JdbcTemplate}, call
068:         * {@link DataSourceUtils#applyTransactionTimeout} for each created JDBC Statement,
069:         * or go through a {@link TransactionAwareDataSourceProxy} which will create
070:         * timeout-aware JDBC Connections and Statements automatically.
071:         *
072:         * <p>Consider defining a {@link LazyConnectionDataSourceProxy} for your target
073:         * DataSource, pointing both this transaction manager and your DAOs to it.
074:         * This will lead to optimized handling of "empty" transactions, i.e. of transactions
075:         * without any JDBC statements executed. A LazyConnectionDataSourceProxy will not fetch
076:         * an actual JDBC Connection from the target DataSource until a Statement gets executed,
077:         * lazily applying the specified transaction settings to the target Connection.
078:         *
079:         * <p>On JDBC 3.0, this transaction manager supports nested transactions via the
080:         * JDBC 3.0 {@link java.sql.Savepoint} mechanism. The
081:         * {@link #setNestedTransactionAllowed "nestedTransactionAllowed"} flag defaults
082:         * to "true", since nested transactions will work without restrictions on JDBC
083:         * drivers that support savepoints (such as the Oracle JDBC driver).
084:         *
085:         * <p>This transaction manager can be used as a replacement for the
086:         * {@link org.springframework.transaction.jta.JtaTransactionManager} in the single
087:         * resource case, as it does not require a container that supports JTA, typically
088:         * in combination with a locally defined JDBC DataSource (e.g. a Jakarta Commons
089:         * DBCP connection pool). Switching between this local strategy and a JTA
090:         * environment is just a matter of configuration!
091:         *
092:         * @author Juergen Hoeller
093:         * @since 02.05.2003
094:         * @see #setNestedTransactionAllowed
095:         * @see java.sql.Savepoint
096:         * @see DataSourceUtils#getConnection(javax.sql.DataSource)
097:         * @see DataSourceUtils#applyTransactionTimeout
098:         * @see DataSourceUtils#releaseConnection
099:         * @see TransactionAwareDataSourceProxy
100:         * @see LazyConnectionDataSourceProxy
101:         * @see org.springframework.jdbc.core.JdbcTemplate
102:         */
103:        public class DataSourceTransactionManager extends
104:                AbstractPlatformTransactionManager implements 
105:                ResourceTransactionManager, InitializingBean {
106:
107:            private DataSource dataSource;
108:
109:            /**
110:             * Create a new DataSourceTransactionManager instance.
111:             * A DataSource has to be set to be able to use it.
112:             * @see #setDataSource
113:             */
114:            public DataSourceTransactionManager() {
115:                setNestedTransactionAllowed(true);
116:            }
117:
118:            /**
119:             * Create a new DataSourceTransactionManager instance.
120:             * @param dataSource JDBC DataSource to manage transactions for
121:             */
122:            public DataSourceTransactionManager(DataSource dataSource) {
123:                this ();
124:                setDataSource(dataSource);
125:                afterPropertiesSet();
126:            }
127:
128:            /**
129:             * Set the JDBC DataSource that this instance should manage transactions for.
130:             * <p>This will typically be a locally defined DataSource, for example a
131:             * Jakarta Commons DBCP connection pool. Alternatively, you can also drive
132:             * transactions for a non-XA J2EE DataSource fetched from JNDI. For an XA
133:             * DataSource, use JtaTransactionManager.
134:             * <p>The DataSource specified here should be the target DataSource to manage
135:             * transactions for, not a TransactionAwareDataSourceProxy. Only data access
136:             * code may work with TransactionAwareDataSourceProxy, while the transaction
137:             * manager needs to work on the underlying target DataSource. If there's
138:             * nevertheless a TransactionAwareDataSourceProxy passed in, it will be
139:             * unwrapped to extract its target DataSource.
140:             * <p><b>The DataSource passed in here needs to return independent Connections.</b>
141:             * The Connections may come from a pool (the typical case), but the DataSource
142:             * must not return thread-scoped / request-scoped Connections or the like.
143:             * @see TransactionAwareDataSourceProxy
144:             * @see org.springframework.transaction.jta.JtaTransactionManager
145:             */
146:            public void setDataSource(DataSource dataSource) {
147:                if (dataSource instanceof  TransactionAwareDataSourceProxy) {
148:                    // If we got a TransactionAwareDataSourceProxy, we need to perform transactions
149:                    // for its underlying target DataSource, else data access code won't see
150:                    // properly exposed transactions (i.e. transactions for the target DataSource).
151:                    this .dataSource = ((TransactionAwareDataSourceProxy) dataSource)
152:                            .getTargetDataSource();
153:                } else {
154:                    this .dataSource = dataSource;
155:                }
156:            }
157:
158:            /**
159:             * Return the JDBC DataSource that this instance manages transactions for.
160:             */
161:            public DataSource getDataSource() {
162:                return this .dataSource;
163:            }
164:
165:            public void afterPropertiesSet() {
166:                if (getDataSource() == null) {
167:                    throw new IllegalArgumentException(
168:                            "Property 'dataSource' is required");
169:                }
170:            }
171:
172:            public Object getResourceFactory() {
173:                return getDataSource();
174:            }
175:
176:            protected Object doGetTransaction() {
177:                DataSourceTransactionObject txObject = new DataSourceTransactionObject();
178:                txObject.setSavepointAllowed(isNestedTransactionAllowed());
179:                ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager
180:                        .getResource(this .dataSource);
181:                txObject.setConnectionHolder(conHolder, false);
182:                return txObject;
183:            }
184:
185:            protected boolean isExistingTransaction(Object transaction) {
186:                DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
187:                return (txObject.getConnectionHolder() != null && txObject
188:                        .getConnectionHolder().isTransactionActive());
189:            }
190:
191:            /**
192:             * This implementation sets the isolation level but ignores the timeout.
193:             */
194:            protected void doBegin(Object transaction,
195:                    TransactionDefinition definition) {
196:                DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
197:                Connection con = null;
198:
199:                try {
200:                    if (txObject.getConnectionHolder() == null
201:                            || txObject.getConnectionHolder()
202:                                    .isSynchronizedWithTransaction()) {
203:                        Connection newCon = this .dataSource.getConnection();
204:                        if (logger.isDebugEnabled()) {
205:                            logger.debug("Acquired Connection [" + newCon
206:                                    + "] for JDBC transaction");
207:                        }
208:                        txObject.setConnectionHolder(new ConnectionHolder(
209:                                newCon), true);
210:                    }
211:
212:                    txObject.getConnectionHolder()
213:                            .setSynchronizedWithTransaction(true);
214:                    con = txObject.getConnectionHolder().getConnection();
215:
216:                    Integer previousIsolationLevel = DataSourceUtils
217:                            .prepareConnectionForTransaction(con, definition);
218:                    txObject.setPreviousIsolationLevel(previousIsolationLevel);
219:
220:                    // Switch to manual commit if necessary. This is very expensive in some JDBC drivers,
221:                    // so we don't want to do it unnecessarily (for example if we've explicitly
222:                    // configured the connection pool to set it already).
223:                    if (con.getAutoCommit()) {
224:                        txObject.setMustRestoreAutoCommit(true);
225:                        if (logger.isDebugEnabled()) {
226:                            logger.debug("Switching JDBC Connection [" + con
227:                                    + "] to manual commit");
228:                        }
229:                        con.setAutoCommit(false);
230:                    }
231:                    txObject.getConnectionHolder().setTransactionActive(true);
232:
233:                    int timeout = determineTimeout(definition);
234:                    if (timeout != TransactionDefinition.TIMEOUT_DEFAULT) {
235:                        txObject.getConnectionHolder().setTimeoutInSeconds(
236:                                timeout);
237:                    }
238:
239:                    // Bind the session holder to the thread.
240:                    if (txObject.isNewConnectionHolder()) {
241:                        TransactionSynchronizationManager
242:                                .bindResource(getDataSource(), txObject
243:                                        .getConnectionHolder());
244:                    }
245:                }
246:
247:                catch (SQLException ex) {
248:                    DataSourceUtils.releaseConnection(con, this .dataSource);
249:                    throw new CannotCreateTransactionException(
250:                            "Could not open JDBC Connection for transaction",
251:                            ex);
252:                }
253:            }
254:
255:            protected Object doSuspend(Object transaction) {
256:                DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
257:                txObject.setConnectionHolder(null);
258:                ConnectionHolder conHolder = (ConnectionHolder) TransactionSynchronizationManager
259:                        .unbindResource(this .dataSource);
260:                return conHolder;
261:            }
262:
263:            protected void doResume(Object transaction,
264:                    Object suspendedResources) {
265:                ConnectionHolder conHolder = (ConnectionHolder) suspendedResources;
266:                TransactionSynchronizationManager.bindResource(this .dataSource,
267:                        conHolder);
268:            }
269:
270:            protected void doCommit(DefaultTransactionStatus status) {
271:                DataSourceTransactionObject txObject = (DataSourceTransactionObject) status
272:                        .getTransaction();
273:                Connection con = txObject.getConnectionHolder().getConnection();
274:                if (status.isDebug()) {
275:                    logger.debug("Committing JDBC transaction on Connection ["
276:                            + con + "]");
277:                }
278:                try {
279:                    con.commit();
280:                } catch (SQLException ex) {
281:                    throw new TransactionSystemException(
282:                            "Could not commit JDBC transaction", ex);
283:                }
284:            }
285:
286:            protected void doRollback(DefaultTransactionStatus status) {
287:                DataSourceTransactionObject txObject = (DataSourceTransactionObject) status
288:                        .getTransaction();
289:                Connection con = txObject.getConnectionHolder().getConnection();
290:                if (status.isDebug()) {
291:                    logger
292:                            .debug("Rolling back JDBC transaction on Connection ["
293:                                    + con + "]");
294:                }
295:                try {
296:                    con.rollback();
297:                } catch (SQLException ex) {
298:                    throw new TransactionSystemException(
299:                            "Could not roll back JDBC transaction", ex);
300:                }
301:            }
302:
303:            protected void doSetRollbackOnly(DefaultTransactionStatus status) {
304:                DataSourceTransactionObject txObject = (DataSourceTransactionObject) status
305:                        .getTransaction();
306:                if (status.isDebug()) {
307:                    logger.debug("Setting JDBC transaction ["
308:                            + txObject.getConnectionHolder().getConnection()
309:                            + "] rollback-only");
310:                }
311:                txObject.setRollbackOnly();
312:            }
313:
314:            protected void doCleanupAfterCompletion(Object transaction) {
315:                DataSourceTransactionObject txObject = (DataSourceTransactionObject) transaction;
316:
317:                // Remove the connection holder from the thread, if exposed.
318:                if (txObject.isNewConnectionHolder()) {
319:                    TransactionSynchronizationManager
320:                            .unbindResource(this .dataSource);
321:                }
322:
323:                // Reset connection.
324:                Connection con = txObject.getConnectionHolder().getConnection();
325:                try {
326:                    if (txObject.isMustRestoreAutoCommit()) {
327:                        con.setAutoCommit(true);
328:                    }
329:                    DataSourceUtils.resetConnectionAfterTransaction(con,
330:                            txObject.getPreviousIsolationLevel());
331:                } catch (Throwable ex) {
332:                    logger
333:                            .debug(
334:                                    "Could not reset JDBC Connection after transaction",
335:                                    ex);
336:                }
337:
338:                if (txObject.isNewConnectionHolder()) {
339:                    if (logger.isDebugEnabled()) {
340:                        logger.debug("Releasing JDBC Connection [" + con
341:                                + "] after transaction");
342:                    }
343:                    DataSourceUtils.releaseConnection(con, this .dataSource);
344:                }
345:
346:                txObject.getConnectionHolder().clear();
347:            }
348:
349:            /**
350:             * DataSource transaction object, representing a ConnectionHolder.
351:             * Used as transaction object by DataSourceTransactionManager.
352:             */
353:            private static class DataSourceTransactionObject extends
354:                    JdbcTransactionObjectSupport {
355:
356:                private boolean newConnectionHolder;
357:
358:                private boolean mustRestoreAutoCommit;
359:
360:                public void setConnectionHolder(
361:                        ConnectionHolder connectionHolder,
362:                        boolean newConnectionHolder) {
363:                    super .setConnectionHolder(connectionHolder);
364:                    this .newConnectionHolder = newConnectionHolder;
365:                }
366:
367:                public boolean isNewConnectionHolder() {
368:                    return newConnectionHolder;
369:                }
370:
371:                public boolean hasTransaction() {
372:                    return (getConnectionHolder() != null && getConnectionHolder()
373:                            .isTransactionActive());
374:                }
375:
376:                public void setMustRestoreAutoCommit(
377:                        boolean mustRestoreAutoCommit) {
378:                    this .mustRestoreAutoCommit = mustRestoreAutoCommit;
379:                }
380:
381:                public boolean isMustRestoreAutoCommit() {
382:                    return mustRestoreAutoCommit;
383:                }
384:
385:                public void setRollbackOnly() {
386:                    getConnectionHolder().setRollbackOnly();
387:                }
388:
389:                public boolean isRollbackOnly() {
390:                    return getConnectionHolder().isRollbackOnly();
391:                }
392:            }
393:
394:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.