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.Savepoint;
020:
021: import org.apache.commons.logging.Log;
022: import org.apache.commons.logging.LogFactory;
023:
024: import org.springframework.transaction.CannotCreateTransactionException;
025: import org.springframework.transaction.NestedTransactionNotSupportedException;
026: import org.springframework.transaction.SavepointManager;
027: import org.springframework.transaction.TransactionException;
028: import org.springframework.transaction.TransactionSystemException;
029: import org.springframework.transaction.TransactionUsageException;
030: import org.springframework.transaction.support.SmartTransactionObject;
031:
032: /**
033: * Convenient base class for JDBC-aware transaction objects.
034: * Can contain a {@link ConnectionHolder}, and implements the
035: * {@link org.springframework.transaction.SavepointManager}
036: * interface based on that ConnectionHolder.
037: *
038: * <p>Allows for programmatic management of JDBC 3.0
039: * {@link java.sql.Savepoint Savepoints}. Spring's
040: * {@link org.springframework.transaction.support.DefaultTransactionStatus}
041: * will automatically delegate to this, as it autodetects transaction
042: * objects that implement the SavepointManager interface.
043: *
044: * <p>Note that savepoints are only supported for drivers which
045: * support JDBC 3.0 or higher.
046: *
047: * @author Juergen Hoeller
048: * @since 1.1
049: */
050: public abstract class JdbcTransactionObjectSupport implements
051: SavepointManager, SmartTransactionObject {
052:
053: private static final Log logger = LogFactory
054: .getLog(JdbcTransactionObjectSupport.class);
055:
056: private ConnectionHolder connectionHolder;
057:
058: private Integer previousIsolationLevel;
059:
060: private boolean savepointAllowed = false;
061:
062: public void setConnectionHolder(ConnectionHolder connectionHolder) {
063: this .connectionHolder = connectionHolder;
064: }
065:
066: public ConnectionHolder getConnectionHolder() {
067: return this .connectionHolder;
068: }
069:
070: public boolean hasConnectionHolder() {
071: return (this .connectionHolder != null);
072: }
073:
074: public void setPreviousIsolationLevel(Integer previousIsolationLevel) {
075: this .previousIsolationLevel = previousIsolationLevel;
076: }
077:
078: public Integer getPreviousIsolationLevel() {
079: return this .previousIsolationLevel;
080: }
081:
082: public void setSavepointAllowed(boolean savepointAllowed) {
083: this .savepointAllowed = savepointAllowed;
084: }
085:
086: public boolean isSavepointAllowed() {
087: return this .savepointAllowed;
088: }
089:
090: //---------------------------------------------------------------------
091: // Implementation of SavepointManager
092: //---------------------------------------------------------------------
093:
094: /**
095: * This implementation creates a JDBC 3.0 Savepoint and returns it.
096: * @see java.sql.Connection#setSavepoint
097: */
098: public Object createSavepoint() throws TransactionException {
099: ConnectionHolder conHolder = getConnectionHolderForSavepoint();
100: try {
101: if (!conHolder.supportsSavepoints()) {
102: throw new NestedTransactionNotSupportedException(
103: "Cannot create a nested transaction because savepoints are not supported by your JDBC driver");
104: }
105: } catch (Throwable ex) {
106: throw new NestedTransactionNotSupportedException(
107: "Cannot create a nested transaction because your JDBC driver is not a JDBC 3.0 driver",
108: ex);
109: }
110: try {
111: return conHolder.createSavepoint();
112: } catch (Throwable ex) {
113: throw new CannotCreateTransactionException(
114: "Could not create JDBC savepoint", ex);
115: }
116: }
117:
118: /**
119: * This implementation rolls back to the given JDBC 3.0 Savepoint.
120: * @see java.sql.Connection#rollback(java.sql.Savepoint)
121: */
122: public void rollbackToSavepoint(Object savepoint)
123: throws TransactionException {
124: try {
125: getConnectionHolderForSavepoint().getConnection().rollback(
126: (Savepoint) savepoint);
127: } catch (Throwable ex) {
128: throw new TransactionSystemException(
129: "Could not roll back to JDBC savepoint", ex);
130: }
131: }
132:
133: /**
134: * This implementation releases the given JDBC 3.0 Savepoint.
135: * @see java.sql.Connection#releaseSavepoint
136: */
137: public void releaseSavepoint(Object savepoint)
138: throws TransactionException {
139: try {
140: getConnectionHolderForSavepoint().getConnection()
141: .releaseSavepoint((Savepoint) savepoint);
142: } catch (Throwable ex) {
143: logger.debug("Could not explicitly release JDBC savepoint",
144: ex);
145: }
146: }
147:
148: protected ConnectionHolder getConnectionHolderForSavepoint()
149: throws TransactionException {
150: if (!isSavepointAllowed()) {
151: throw new NestedTransactionNotSupportedException(
152: "Transaction manager does not allow nested transactions");
153: }
154: if (!hasConnectionHolder()) {
155: throw new TransactionUsageException(
156: "Cannot create nested transaction if not exposing a JDBC transaction");
157: }
158: return getConnectionHolder();
159: }
160:
161: }
|