KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > jdbc > datasource > IsolationLevelDataSourceAdapter


1 /*
2  * Copyright 2002-2007 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.jdbc.datasource;
18
19 import java.sql.Connection JavaDoc;
20 import java.sql.SQLException JavaDoc;
21
22 import org.springframework.core.Constants;
23 import org.springframework.transaction.TransactionDefinition;
24 import org.springframework.transaction.support.DefaultTransactionDefinition;
25 import org.springframework.transaction.support.TransactionSynchronizationManager;
26
27 /**
28  * An adapter for a target {@link javax.sql.DataSource}, applying the current
29  * Spring transaction's isolation level (and potentially specified user credentials)
30  * to every <code>getConnection</code> call. Also applies the read-only flag,
31  * if specified.
32  *
33  * <p>Can be used to proxy a target JNDI DataSource that does not have the
34  * desired isolation level (and user credentials) configured. Client code
35  * can work with this DataSource as usual, not worrying about such settings.
36  *
37  * <p>Inherits the capability to apply specific user credentials from its superclass
38  * {@link UserCredentialsDataSourceAdapter}; see the latter's javadoc for details
39  * on that functionality (e.g. {@link #setCredentialsForCurrentThread}).
40  *
41  * <p><b>WARNING:</b> This adapter simply calls
42  * {@link java.sql.Connection#setTransactionIsolation} and/or
43  * {@link java.sql.Connection#setReadOnly} for every Connection obtained from it.
44  * It does, however, <i>not</i> reset those settings; it rather expects the target
45  * DataSource to perform such resetting as part of its connection pool handling.
46  * <b>Make sure that the target DataSource properly cleans up such transaction state.</b>
47  *
48  * @author Juergen Hoeller
49  * @since 2.0.3
50  * @see #setIsolationLevel
51  * @see #setIsolationLevelName
52  * @see #setUsername
53  * @see #setPassword
54  */

55 public class IsolationLevelDataSourceAdapter extends UserCredentialsDataSourceAdapter {
56
57     /** Constants instance for TransactionDefinition */
58     private static final Constants constants = new Constants(TransactionDefinition.class);
59
60     private Integer JavaDoc isolationLevel;
61
62
63     /**
64      * Set the default isolation level by the name of the corresponding constant
65      * in {@link org.springframework.transaction.TransactionDefinition}, e.g.
66      * "ISOLATION_SERIALIZABLE".
67      * <p>If not specified, the target DataSource's default will be used.
68      * Note that a transaction-specific isolation value will always override
69      * any isolation setting specified at the DataSource level.
70      * @param constantName name of the constant
71      * @see org.springframework.transaction.TransactionDefinition#ISOLATION_READ_UNCOMMITTED
72      * @see org.springframework.transaction.TransactionDefinition#ISOLATION_READ_COMMITTED
73      * @see org.springframework.transaction.TransactionDefinition#ISOLATION_REPEATABLE_READ
74      * @see org.springframework.transaction.TransactionDefinition#ISOLATION_SERIALIZABLE
75      * @see #setIsolationLevel
76      */

77     public final void setIsolationLevelName(String JavaDoc constantName) throws IllegalArgumentException JavaDoc {
78         if (constantName == null || !constantName.startsWith(DefaultTransactionDefinition.PREFIX_ISOLATION)) {
79             throw new IllegalArgumentException JavaDoc("Only isolation constants allowed");
80         }
81         setIsolationLevel(constants.asNumber(constantName).intValue());
82     }
83
84     /**
85      * Specify the default isolation level to use for Connection retrieval,
86      * according to the JDBC {@link java.sql.Connection} constants
87      * (equivalent to the corresponding Spring
88      * {@link org.springframework.transaction.TransactionDefinition} constants).
89      * <p>If not specified, the target DataSource's default will be used.
90      * Note that a transaction-specific isolation value will always override
91      * any isolation setting specified at the DataSource level.
92      * @see java.sql.Connection#TRANSACTION_READ_UNCOMMITTED
93      * @see java.sql.Connection#TRANSACTION_READ_COMMITTED
94      * @see java.sql.Connection#TRANSACTION_REPEATABLE_READ
95      * @see java.sql.Connection#TRANSACTION_SERIALIZABLE
96      * @see org.springframework.transaction.TransactionDefinition#ISOLATION_READ_UNCOMMITTED
97      * @see org.springframework.transaction.TransactionDefinition#ISOLATION_READ_COMMITTED
98      * @see org.springframework.transaction.TransactionDefinition#ISOLATION_REPEATABLE_READ
99      * @see org.springframework.transaction.TransactionDefinition#ISOLATION_SERIALIZABLE
100      * @see org.springframework.transaction.TransactionDefinition#getIsolationLevel()
101      * @see org.springframework.transaction.support.TransactionSynchronizationManager#getCurrentTransactionIsolationLevel()
102      */

103     public void setIsolationLevel(int isolationLevel) {
104         if (!constants.getValues(DefaultTransactionDefinition.PREFIX_ISOLATION).contains(new Integer JavaDoc(isolationLevel))) {
105             throw new IllegalArgumentException JavaDoc("Only values of isolation constants allowed");
106         }
107         this.isolationLevel =
108                 (isolationLevel != TransactionDefinition.ISOLATION_DEFAULT ? new Integer JavaDoc(isolationLevel) : null);
109     }
110
111     /**
112      * Return the statically specified isolation level,
113      * or <code>null</code> if none.
114      */

115     protected Integer JavaDoc getIsolationLevel() {
116         return this.isolationLevel;
117     }
118
119
120     /**
121      * Applies the current isolation level value and read-only flag
122      * to the returned Connection.
123      * @see #getCurrentIsolationLevel()
124      * @see #getCurrentReadOnlyFlag()
125      */

126     protected Connection JavaDoc doGetConnection(String JavaDoc username, String JavaDoc password) throws SQLException JavaDoc {
127         Connection JavaDoc con = super.doGetConnection(username, password);
128         Boolean JavaDoc readOnlyToUse = getCurrentReadOnlyFlag();
129         if (readOnlyToUse != null) {
130             con.setReadOnly(readOnlyToUse.booleanValue());
131         }
132         Integer JavaDoc isolationLevelToUse = getCurrentIsolationLevel();
133         if (isolationLevelToUse != null) {
134             con.setTransactionIsolation(isolationLevelToUse.intValue());
135         }
136         return con;
137     }
138
139     /**
140      * Determine the current isolation level: either the transaction's
141      * isolation level or a statically defined isolation level.
142      * @return the current isolation level, or <code>null</code> if none
143      * @see org.springframework.transaction.support.TransactionSynchronizationManager#getCurrentTransactionIsolationLevel()
144      * @see #setIsolationLevel
145      */

146     protected Integer JavaDoc getCurrentIsolationLevel() {
147         Integer JavaDoc isolationLevelToUse = TransactionSynchronizationManager.getCurrentTransactionIsolationLevel();
148         if (isolationLevelToUse == null) {
149             isolationLevelToUse = getIsolationLevel();
150         }
151         return isolationLevelToUse;
152     }
153
154     /**
155      * Determine the current read-only flag: by default,
156      * the transaction's read-only hint.
157      * @return whether there is a read-only hint for the current scope
158      * @see org.springframework.transaction.support.TransactionSynchronizationManager#isCurrentTransactionReadOnly()
159      */

160     protected Boolean JavaDoc getCurrentReadOnlyFlag() {
161         boolean txReadOnly = TransactionSynchronizationManager.isCurrentTransactionReadOnly();
162         return (txReadOnly ? Boolean.TRUE : null);
163     }
164
165 }
166
Popular Tags