Skip to content

Commit d99fb4f

Browse files
committed
HHH-9503 - Consistently accept numeric value or Connection constant field name for configuring transaction isolation
1 parent 1d61210 commit d99fb4f

File tree

12 files changed

+407
-48
lines changed

12 files changed

+407
-48
lines changed

hibernate-c3p0/src/main/java/org/hibernate/c3p0/internal/C3P0ConnectionProvider.java

Lines changed: 2 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -197,15 +197,8 @@ public void configure(Map props) {
197197
throw new HibernateException( LOG.unableToInstantiateC3p0ConnectionPool(), e );
198198
}
199199

200-
final String i = (String) props.get( Environment.ISOLATION );
201-
if ( StringHelper.isEmpty( i ) ) {
202-
isolation = null;
203-
}
204-
else {
205-
isolation = Integer.valueOf( i );
206-
LOG.jdbcIsolationLevel( Environment.isolationLevelToString( isolation ) );
207-
}
208-
200+
isolation = ConnectionProviderInitiator.extractIsolation( props );
201+
LOG.jdbcIsolationLevel( ConnectionProviderInitiator.toIsolationNiceName( isolation ) );
209202
}
210203

211204
@Override
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/*
2+
* Hibernate, Relational Persistence for Idiomatic Java
3+
*
4+
* License: GNU Lesser General Public License (LGPL), version 2.1 or later.
5+
* See the lgpl.txt file in the root directory or <http://www.gnu.org/licenses/lgpl-2.1.html>.
6+
*/
7+
package org.hibernate.test.c3p0;
8+
9+
import org.hibernate.boot.registry.StandardServiceRegistry;
10+
import org.hibernate.boot.registry.StandardServiceRegistryBuilder;
11+
import org.hibernate.c3p0.internal.C3P0ConnectionProvider;
12+
import org.hibernate.connection.BaseTransactionIsolationConfigTest;
13+
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
14+
import org.hibernate.service.spi.ServiceRegistryImplementor;
15+
16+
import org.junit.Before;
17+
18+
/**
19+
* @author Steve Ebersole
20+
*/
21+
public class C3p0TransactionIsolationConfigTest extends BaseTransactionIsolationConfigTest {
22+
private StandardServiceRegistry ssr;
23+
24+
@Before
25+
public void setUp() {
26+
ssr = new StandardServiceRegistryBuilder().build();
27+
}
28+
29+
@Override
30+
protected ConnectionProvider getConnectionProviderUnderTest() {
31+
C3P0ConnectionProvider provider = new C3P0ConnectionProvider();
32+
provider.injectServices( (ServiceRegistryImplementor) ssr );
33+
return provider;
34+
}
35+
}

hibernate-core/src/main/java/org/hibernate/cfg/Environment.java

Lines changed: 4 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,15 @@
88

99
import java.io.IOException;
1010
import java.io.InputStream;
11-
import java.sql.Connection;
1211
import java.sql.Timestamp;
13-
import java.util.Collections;
1412
import java.util.HashMap;
1513
import java.util.Map;
1614
import java.util.Properties;
1715

1816
import org.hibernate.HibernateException;
1917
import org.hibernate.Version;
2018
import org.hibernate.bytecode.spi.BytecodeProvider;
19+
import org.hibernate.engine.jdbc.connections.internal.ConnectionProviderInitiator;
2120
import org.hibernate.internal.CoreMessageLogger;
2221
import org.hibernate.internal.util.ConfigHelper;
2322
import org.hibernate.internal.util.config.ConfigurationHelper;
@@ -160,7 +159,6 @@ public final class Environment implements AvailableSettings {
160159
private static final boolean JVM_HAS_TIMESTAMP_BUG;
161160

162161
private static final Properties GLOBAL_PROPERTIES;
163-
private static final Map<Integer,String> ISOLATION_LEVELS;
164162

165163
private static final Map OBSOLETE_PROPERTIES = new HashMap();
166164
private static final Map RENAMED_PROPERTIES = new HashMap();
@@ -189,13 +187,6 @@ public static void verifyProperties(Map<?,?> configurationValues) {
189187
static {
190188
Version.logVersion();
191189

192-
Map<Integer,String> temp = new HashMap<Integer,String>();
193-
temp.put( Connection.TRANSACTION_NONE, "NONE" );
194-
temp.put( Connection.TRANSACTION_READ_UNCOMMITTED, "READ_UNCOMMITTED" );
195-
temp.put( Connection.TRANSACTION_READ_COMMITTED, "READ_COMMITTED" );
196-
temp.put( Connection.TRANSACTION_REPEATABLE_READ, "REPEATABLE_READ" );
197-
temp.put( Connection.TRANSACTION_SERIALIZABLE, "SERIALIZABLE" );
198-
ISOLATION_LEVELS = Collections.unmodifiableMap( temp );
199190
GLOBAL_PROPERTIES = new Properties();
200191
//Set USE_REFLECTION_OPTIMIZER to false to fix HHH-227
201192
GLOBAL_PROPERTIES.setProperty( USE_REFLECTION_OPTIMIZER, Boolean.FALSE.toString() );
@@ -314,14 +305,11 @@ public static Properties getProperties() {
314305
}
315306

316307
/**
317-
* Get the name of a JDBC transaction isolation level
318-
*
319-
* @see java.sql.Connection
320-
* @param isolation as defined by <tt>java.sql.Connection</tt>
321-
* @return a human-readable name
308+
* @deprecated Use {@link ConnectionProviderInitiator#toIsolationNiceName} instead
322309
*/
310+
@Deprecated
323311
public static String isolationLevelToString(int isolation) {
324-
return ISOLATION_LEVELS.get( isolation );
312+
return ConnectionProviderInitiator.toIsolationNiceName( isolation );
325313
}
326314

327315
public static BytecodeProvider buildBytecodeProvider(Properties properties) {

hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/ConnectionProviderInitiator.java

Lines changed: 122 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,21 +9,23 @@
99
import java.beans.BeanInfo;
1010
import java.beans.PropertyDescriptor;
1111
import java.lang.reflect.Method;
12+
import java.sql.Connection;
1213
import java.util.HashMap;
1314
import java.util.HashSet;
1415
import java.util.Map;
1516
import java.util.Properties;
1617
import java.util.Set;
18+
import java.util.concurrent.ConcurrentHashMap;
1719

1820
import org.hibernate.HibernateException;
1921
import org.hibernate.MultiTenancyStrategy;
2022
import org.hibernate.boot.registry.StandardServiceInitiator;
2123
import org.hibernate.boot.registry.selector.spi.StrategySelector;
2224
import org.hibernate.cfg.AvailableSettings;
23-
import org.hibernate.cfg.Environment;
2425
import org.hibernate.engine.jdbc.connections.spi.ConnectionProvider;
2526
import org.hibernate.internal.CoreMessageLogger;
2627
import org.hibernate.internal.log.DeprecationLogger;
28+
import org.hibernate.internal.util.StringHelper;
2729
import org.hibernate.internal.util.beans.BeanInfoHelper;
2830
import org.hibernate.service.spi.ServiceRegistryImplementor;
2931

@@ -108,7 +110,7 @@ public ConnectionProvider initiateService(Map configurationValues, ServiceRegist
108110
if ( providerName != null ) {
109111
connectionProvider = instantiateExplicitConnectionProvider( providerName, strategySelector );
110112
}
111-
else if ( configurationValues.get( Environment.DATASOURCE ) != null ) {
113+
else if ( configurationValues.get( AvailableSettings.DATASOURCE ) != null ) {
112114
connectionProvider = new DatasourceConnectionProviderImpl();
113115
}
114116

@@ -131,7 +133,7 @@ else if ( configurationValues.get( Environment.DATASOURCE ) != null ) {
131133
}
132134

133135
if ( connectionProvider == null ) {
134-
if ( configurationValues.get( Environment.URL ) != null ) {
136+
if ( configurationValues.get( AvailableSettings.URL ) != null ) {
135137
connectionProvider = new DriverManagerConnectionProviderImpl();
136138
}
137139
}
@@ -169,7 +171,7 @@ public void processBeanInfo(BeanInfo beanInfo) throws Exception {
169171
}
170172

171173
private String getConfiguredConnectionProviderName( Map configurationValues ) {
172-
String providerName = (String) configurationValues.get( Environment.CONNECTION_PROVIDER );
174+
String providerName = (String) configurationValues.get( AvailableSettings.CONNECTION_PROVIDER );
173175
if ( LEGACY_CONNECTION_PROVIDER_MAPPING.containsKey( providerName ) ) {
174176
final String actualProviderName = LEGACY_CONNECTION_PROVIDER_MAPPING.get( providerName );
175177
DeprecationLogger.DEPRECATION_LOGGER.connectionProviderClassDeprecated( providerName, actualProviderName );
@@ -274,15 +276,15 @@ public static Properties getConnectionProperties(Map<?,?> properties) {
274276
}
275277
final String key = (String) entry.getKey();
276278
final String value = (String) entry.getValue();
277-
if ( key.startsWith( Environment.CONNECTION_PREFIX ) ) {
279+
if ( key.startsWith( AvailableSettings.CONNECTION_PREFIX ) ) {
278280
if ( SPECIAL_PROPERTIES.contains( key ) ) {
279-
if ( Environment.USER.equals( key ) ) {
281+
if ( AvailableSettings.USER.equals( key ) ) {
280282
result.setProperty( "user", value );
281283
}
282284
}
283285
else {
284286
result.setProperty(
285-
key.substring( Environment.CONNECTION_PREFIX.length() + 1 ),
287+
key.substring( AvailableSettings.CONNECTION_PREFIX.length() + 1 ),
286288
value
287289
);
288290
}
@@ -296,15 +298,45 @@ else if ( CONDITIONAL_PROPERTIES.containsKey( key ) ) {
296298

297299
private static final Set<String> SPECIAL_PROPERTIES;
298300

301+
private static final Map<String,Integer> ISOLATION_VALUE_MAP;
302+
private static final Map<Integer, String> ISOLATION_VALUE_CONSTANT_NAME_MAP;
303+
private static final Map<Integer, String> ISOLATION_VALUE_NICE_NAME_MAP;
304+
299305
static {
300306
SPECIAL_PROPERTIES = new HashSet<String>();
301-
SPECIAL_PROPERTIES.add( Environment.DATASOURCE );
302-
SPECIAL_PROPERTIES.add( Environment.URL );
303-
SPECIAL_PROPERTIES.add( Environment.CONNECTION_PROVIDER );
304-
SPECIAL_PROPERTIES.add( Environment.POOL_SIZE );
305-
SPECIAL_PROPERTIES.add( Environment.ISOLATION );
306-
SPECIAL_PROPERTIES.add( Environment.DRIVER );
307-
SPECIAL_PROPERTIES.add( Environment.USER );
307+
SPECIAL_PROPERTIES.add( AvailableSettings.DATASOURCE );
308+
SPECIAL_PROPERTIES.add( AvailableSettings.URL );
309+
SPECIAL_PROPERTIES.add( AvailableSettings.CONNECTION_PROVIDER );
310+
SPECIAL_PROPERTIES.add( AvailableSettings.POOL_SIZE );
311+
SPECIAL_PROPERTIES.add( AvailableSettings.ISOLATION );
312+
SPECIAL_PROPERTIES.add( AvailableSettings.DRIVER );
313+
SPECIAL_PROPERTIES.add( AvailableSettings.USER );
314+
315+
ISOLATION_VALUE_MAP = new ConcurrentHashMap<String, Integer>();
316+
ISOLATION_VALUE_MAP.put( "TRANSACTION_NONE", Connection.TRANSACTION_NONE );
317+
ISOLATION_VALUE_MAP.put( "NONE", Connection.TRANSACTION_NONE );
318+
ISOLATION_VALUE_MAP.put( "TRANSACTION_READ_UNCOMMITTED", Connection.TRANSACTION_READ_UNCOMMITTED );
319+
ISOLATION_VALUE_MAP.put( "READ_UNCOMMITTED", Connection.TRANSACTION_READ_UNCOMMITTED );
320+
ISOLATION_VALUE_MAP.put( "TRANSACTION_READ_COMMITTED", Connection.TRANSACTION_READ_COMMITTED );
321+
ISOLATION_VALUE_MAP.put( "READ_COMMITTED", Connection.TRANSACTION_READ_COMMITTED );
322+
ISOLATION_VALUE_MAP.put( "TRANSACTION_REPEATABLE_READ", Connection.TRANSACTION_REPEATABLE_READ );
323+
ISOLATION_VALUE_MAP.put( "REPEATABLE_READ", Connection.TRANSACTION_REPEATABLE_READ );
324+
ISOLATION_VALUE_MAP.put( "TRANSACTION_SERIALIZABLE", Connection.TRANSACTION_SERIALIZABLE );
325+
ISOLATION_VALUE_MAP.put( "SERIALIZABLE", Connection.TRANSACTION_SERIALIZABLE );
326+
327+
ISOLATION_VALUE_CONSTANT_NAME_MAP = new ConcurrentHashMap<Integer, String>();
328+
ISOLATION_VALUE_CONSTANT_NAME_MAP.put( Connection.TRANSACTION_NONE, "TRANSACTION_NONE" );
329+
ISOLATION_VALUE_CONSTANT_NAME_MAP.put( Connection.TRANSACTION_READ_UNCOMMITTED, "TRANSACTION_READ_UNCOMMITTED" );
330+
ISOLATION_VALUE_CONSTANT_NAME_MAP.put( Connection.TRANSACTION_READ_COMMITTED, "TRANSACTION_READ_COMMITTED" );
331+
ISOLATION_VALUE_CONSTANT_NAME_MAP.put( Connection.TRANSACTION_REPEATABLE_READ, "TRANSACTION_REPEATABLE_READ" );
332+
ISOLATION_VALUE_CONSTANT_NAME_MAP.put( Connection.TRANSACTION_SERIALIZABLE, "TRANSACTION_SERIALIZABLE" );
333+
334+
ISOLATION_VALUE_NICE_NAME_MAP = new ConcurrentHashMap<Integer, String>();
335+
ISOLATION_VALUE_NICE_NAME_MAP.put( Connection.TRANSACTION_NONE, "NONE" );
336+
ISOLATION_VALUE_NICE_NAME_MAP.put( Connection.TRANSACTION_READ_UNCOMMITTED, "READ_UNCOMMITTED" );
337+
ISOLATION_VALUE_NICE_NAME_MAP.put( Connection.TRANSACTION_READ_COMMITTED, "READ_COMMITTED" );
338+
ISOLATION_VALUE_NICE_NAME_MAP.put( Connection.TRANSACTION_REPEATABLE_READ, "REPEATABLE_READ" );
339+
ISOLATION_VALUE_NICE_NAME_MAP.put( Connection.TRANSACTION_SERIALIZABLE, "SERIALIZABLE" );
308340
}
309341

310342
// Connection properties (map value) that automatically need set if the
@@ -315,6 +347,81 @@ else if ( CONDITIONAL_PROPERTIES.containsKey( key ) ) {
315347
static {
316348
CONDITIONAL_PROPERTIES = new HashMap<String, String>();
317349
// Oracle requires that includeSynonyms=true in order for getColumns to work using a table synonym name.
318-
CONDITIONAL_PROPERTIES.put( Environment.ENABLE_SYNONYMS, "includeSynonyms" );
350+
CONDITIONAL_PROPERTIES.put( AvailableSettings.ENABLE_SYNONYMS, "includeSynonyms" );
351+
}
352+
353+
public static Integer extractIsolation(Map settings) {
354+
return interpretIsolation( settings.get( AvailableSettings.ISOLATION ) );
355+
}
356+
357+
public static Integer interpretIsolation(Object setting) {
358+
if ( setting == null ) {
359+
return null;
360+
}
361+
362+
if ( Number.class.isInstance( setting ) ) {
363+
return ( (Number) setting ).intValue();
364+
}
365+
366+
final String settingAsString = setting.toString();
367+
if ( StringHelper.isEmpty( settingAsString ) ) {
368+
return null;
369+
}
370+
371+
if ( ISOLATION_VALUE_MAP.containsKey( settingAsString ) ) {
372+
return ISOLATION_VALUE_MAP.get( settingAsString );
373+
}
374+
375+
// it could be a String representation of the isolation numeric value...
376+
try {
377+
return Integer.valueOf( settingAsString );
378+
}
379+
catch (NumberFormatException ignore) {
380+
}
381+
382+
throw new HibernateException( "Could not interpret transaction isolation setting [" + setting + "]" );
383+
}
384+
385+
/**
386+
* Gets the {@link Connection} constant name corresponding to the given isolation.
387+
*
388+
* @param isolation The transaction isolation numeric value.
389+
*
390+
* @return The corresponding Connection constant name.
391+
*
392+
* @throws HibernateException If the given isolation does not map to JDBC standard isolation
393+
*
394+
* @see #toIsolationNiceName
395+
*/
396+
public static String toIsolationConnectionConstantName(Integer isolation) {
397+
final String name = ISOLATION_VALUE_CONSTANT_NAME_MAP.get( isolation );
398+
if ( name == null ) {
399+
throw new HibernateException(
400+
"Could not convert isolation value [" + isolation + "] to java.sql.Connection constant name"
401+
);
402+
}
403+
return name;
404+
}
405+
406+
/**
407+
* Get the name of a JDBC transaction isolation level
408+
*
409+
* @param isolation The transaction isolation numeric value.
410+
*
411+
* @return a nice human-readable name
412+
*
413+
* @see #toIsolationConnectionConstantName
414+
*/
415+
public static String toIsolationNiceName(Integer isolation) {
416+
String name = null;
417+
418+
if ( isolation != null ) {
419+
name = ISOLATION_VALUE_NICE_NAME_MAP.get( isolation );
420+
}
421+
422+
if ( name == null ) {
423+
name = "<unknown>";
424+
}
425+
return name;
319426
}
320427
}

hibernate-core/src/main/java/org/hibernate/engine/jdbc/connections/internal/DriverManagerConnectionProviderImpl.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -163,9 +163,9 @@ private ConnectionCreator buildCreator(Map configurationValues) {
163163
log.autoCommitMode( autoCommit );
164164
connectionCreatorBuilder.setAutoCommit( autoCommit );
165165

166-
final Integer isolation = ConfigurationHelper.getInteger( AvailableSettings.ISOLATION, configurationValues );
166+
final Integer isolation = ConnectionProviderInitiator.extractIsolation( configurationValues );
167167
if ( isolation != null ) {
168-
log.jdbcIsolationLevel( Environment.isolationLevelToString( isolation ) );
168+
log.jdbcIsolationLevel( ConnectionProviderInitiator.toIsolationNiceName( isolation ) );
169169
}
170170
connectionCreatorBuilder.setIsolation( isolation );
171171

0 commit comments

Comments
 (0)