blob: 2938da2bd29b1bb7fbd1fc60cebed18eddb08edf [file] [log] [blame]
/*******************************************************************************
* Copyright (c) 2010 Dies Koper (Fujitsu) All rights reserved.
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v1.0 and Eclipse Distribution License v. 1.0
* which accompanies this distribution.
* The Eclipse Public License is available at http://www.eclipse.org/legal/epl-v10.html
* and the Eclipse Distribution License is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* Contributors:
* Created Jan 10, 2010 - Dies Koper (Fujitsu), patterned after SybaseTransactionIsolationListener
* bug 288715: Tests: Several Core LRG tests hang on Symfoware.
******************************************************************************/
package org.eclipse.persistence.testing.framework;
import java.sql.Connection;
import java.sql.SQLException;
import java.sql.Statement;
import java.util.HashMap;
import java.util.Map;
import org.eclipse.persistence.internal.databaseaccess.DatabaseAccessor;
import org.eclipse.persistence.sessions.SessionEvent;
import org.eclipse.persistence.sessions.SessionEventAdapter;
/*
* Symfoware in general is configured to use transaction isolation level
* READ_COMMITTED or SERIALIZABLE.<br/>
* That causes a few tests to hang, or fail with an error message saying that the table is locked
* (depending on a setting on the database side): these tests begin transaction, update a row,
* then (before the transaction has been committed) attempt to read the row through another connection.
*
* To allow these reads to go through (and read the uncommitted data) connection isolation level
* should be temporary switched to READ_UNCOMMITTED.
*
* This class switches the acquired connection to READ_UNCOMMITTED and then sets back the original
* isolation level before connection is released.
*
* Note that for the above scenario only read connections require level READ_UNCOMMITTED.
*
* @author Dies Koper
*/
public class TransactionIsolationLevelSwitchListener extends
SessionEventAdapter {
Map<Connection, String> connections = new HashMap<Connection, String>();
public void postAcquireConnection(SessionEvent event) {
Connection conn = ((DatabaseAccessor) event.getResult())
.getConnection();
Statement stmt1 = null;
String isolationLevel = "";
try {
int i = conn.getTransactionIsolation();
switch (i) {
case 1:
isolationLevel = "READ UNCOMMITTED";
break;
case 2:
isolationLevel = "READ COMMITTED";
break;
case 4:
isolationLevel = "REPEATABLE READ";
break;
case 8:
isolationLevel = "SERIALIZABLE";
break;
}
if (i > 0) {
// If conn1 began transaction and updated the row (but hasn't
// committed the transaction yet),
// then conn2 should be able to read the original (not updated)
// state of the row.
// Without this conn2 reading the row hangs on Symfoware.
stmt1 = conn.createStatement();
stmt1.execute("set transaction isolation level READ UNCOMMITTED");
connections.put(conn, isolationLevel);
}
} catch (SQLException sqlException) {
throw new TestProblemException("postAcquireConnection failed. ",
sqlException);
} finally {
if (stmt1 != null) {
try {
stmt1.close();
} catch (SQLException ex) {
// Ignore
}
}
}
}
public void preReleaseConnection(SessionEvent event) {
Connection conn = ((DatabaseAccessor) event.getResult())
.getConnection();
Statement stmt = null;
try {
String isolationLevel = connections.remove(conn);
if (isolationLevel != null) {
// reset the original transaction isolation.
stmt = conn.createStatement();
stmt.execute("set transaction isolation level "
+ isolationLevel);
stmt.close();
}
} catch (SQLException sqlException) {
throw new TestProblemException("preReleaseConnection failed. ",
sqlException);
} finally {
if (stmt != null) {
try {
stmt.close();
} catch (SQLException ex) {
// Ignore
}
}
}
}
}