blob: 7f64bebb72811c19979a98a2f28a2aecd8f07bf0 [file] [log] [blame]
/*
* Copyright (c) 2010, 2021 Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 2010, 2015 SAP All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0 which is available at
* http://www.eclipse.org/legal/epl-2.0,
* or the Eclipse Distribution License v. 1.0 which is available at
* http://www.eclipse.org/org/documents/edl-v10.php.
*
* SPDX-License-Identifier: EPL-2.0 OR BSD-3-Clause
*/
// Contributors:
// Created Oct 1st, 2010 - Adrian Görler, patterned after SybaseTransactionIsolationListener
// bug 326777: Some Core LRG tests hang on MaxDB.
package org.eclipse.persistence.testing.framework;
import java.sql.Connection;
import java.sql.SQLException;
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;
/*
* <p>SAP MaxDB in general is configured to use transaction isolation level
* READ_COMMITTED or SERIALIZABLE.</p>
* 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 agoerler
*/
class JDBCIsoLevelSwitchListener extends SessionEventAdapter {
Map<Connection, Integer> connections = new HashMap<Connection, Integer>();
@Override
public void postAcquireConnection(SessionEvent event) {
Connection conn = ((DatabaseAccessor) event.getResult()).getConnection();
int old;
try {
old = conn.getTransactionIsolation();
if (old != Connection.TRANSACTION_READ_UNCOMMITTED) {
conn.setTransactionIsolation(Connection.TRANSACTION_READ_UNCOMMITTED);
connections.put(conn, old);
}
} catch (SQLException sqlException) {
throw new TestProblemException("postAcquireConnection failed. ", sqlException);
}
}
@Override
public void preReleaseConnection(SessionEvent event) {
Connection conn = ((DatabaseAccessor) event.getResult()).getConnection();
try {
Integer old = connections.remove(conn);
if (old != null) {
conn.setTransactionIsolation(old);
}
} catch (SQLException sqlException) {
throw new TestProblemException("preReleaseConnection failed. ", sqlException);
}
}
}