提交 074260d2 authored 作者: Thomas Mueller's avatar Thomas Mueller

Closing a Statement or PreparedStatement at the same time as executing a…

Closing a Statement or PreparedStatement at the same time as executing a statement could throw a strange exception.
上级 bf6c990c
......@@ -294,15 +294,15 @@ public class JdbcConnection extends TraceObject implements Connection {
try {
debugCodeCall("close");
openStackTrace = null;
if (executingStatement != null) {
executingStatement.cancel();
}
if (session == null) {
return;
}
session.cancel();
try {
synchronized (session) {
synchronized (session) {
if (executingStatement != null) {
executingStatement.cancel();
}
session.cancel();
try {
if (!session.isClosed()) {
try {
// roll back unless that would require to re-connect
......@@ -316,9 +316,9 @@ public class JdbcConnection extends TraceObject implements Connection {
session.close();
}
}
} finally {
session = null;
}
} finally {
session = null;
}
} catch (Exception e) {
throw logAndConvert(e);
......
......@@ -85,20 +85,20 @@ public class JdbcPreparedStatement extends JdbcStatement implements PreparedStat
if (isDebugEnabled()) {
debugCodeAssign("ResultSet", TraceObject.RESULT_SET, id, "executeQuery()");
}
checkClosed();
closeOldResultSet();
ResultInterface result;
boolean scrollable = resultSetType != ResultSet.TYPE_FORWARD_ONLY;
boolean updatable = resultSetConcurrency == ResultSet.CONCUR_UPDATABLE;
synchronized (session) {
checkClosed();
closeOldResultSet();
ResultInterface result;
boolean scrollable = resultSetType != ResultSet.TYPE_FORWARD_ONLY;
boolean updatable = resultSetConcurrency == ResultSet.CONCUR_UPDATABLE;
try {
setExecutingStatement(command);
result = command.executeQuery(maxRows, scrollable);
} finally {
setExecutingStatement(null);
}
resultSet = new JdbcResultSet(conn, this, result, id, closedByResultSet, scrollable, updatable);
}
resultSet = new JdbcResultSet(conn, this, result, id, closedByResultSet, scrollable, updatable);
return resultSet;
} catch (Exception e) {
throw logAndConvert(e);
......@@ -165,9 +165,9 @@ public class JdbcPreparedStatement extends JdbcStatement implements PreparedStat
}
checkClosedForWrite();
try {
closeOldResultSet();
boolean returnsResultSet;
synchronized (conn.getSession()) {
closeOldResultSet();
try {
setExecutingStatement(command);
if (command.isQuery()) {
......
......@@ -64,10 +64,10 @@ public class JdbcStatement extends TraceObject implements Statement {
if (isDebugEnabled()) {
debugCodeAssign("ResultSet", TraceObject.RESULT_SET, id, "executeQuery(" + quote(sql) + ")");
}
checkClosed();
closeOldResultSet();
sql = conn.translateSQL(sql, escapeProcessing);
synchronized (session) {
checkClosed();
closeOldResultSet();
sql = conn.translateSQL(sql, escapeProcessing);
CommandInterface command = conn.prepareCommand(sql, fetchSize);
ResultInterface result;
boolean scrollable = resultSetType != ResultSet.TYPE_FORWARD_ONLY;
......@@ -234,9 +234,11 @@ public class JdbcStatement extends TraceObject implements Statement {
public void close() throws SQLException {
try {
debugCodeCall("close");
closeOldResultSet();
if (conn != null) {
conn = null;
synchronized (session) {
closeOldResultSet();
if (conn != null) {
conn = null;
}
}
} catch (Exception e) {
throw logAndConvert(e);
......
/*
* Copyright 2004-2010 H2 Group. Multiple-Licensed under the H2 License,
* Version 1.0, and under the Eclipse Public License, Version 1.0
* (http://h2database.com/html/license.html).
* Initial Developer: H2 Group
*/
package org.h2.test.unit;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.PreparedStatement;
import java.sql.SQLException;
import java.sql.Statement;
import org.h2.constant.ErrorCode;
import org.h2.test.TestBase;
/**
* Test concurrent access to JDBC objects.
*/
public class TestConcurrent extends TestBase {
/**
* Run just this test.
*
* @param a ignored
*/
public static void main(String... a) throws Exception {
TestBase.createCaller().init().test();
}
public void test() throws Exception {
String url = "jdbc:h2:mem:";
for (int i = 0; i < 50; i++) {
final int x = i % 4;
final Connection conn = DriverManager.getConnection(url);
final Statement stat = conn.createStatement();
stat.execute("create table test(id int primary key)");
String sql = "";
switch (x % 6) {
case 0:
sql = "select 1";
break;
case 1:
case 2:
sql = "delete from test";
break;
}
final PreparedStatement prep = conn.prepareStatement(sql);
final SQLException[] ex = new SQLException[1];
Thread t = new Thread() {
public void run() {
try {
while (!conn.isClosed()) {
switch (x % 6) {
case 0:
prep.executeQuery();
break;
case 1:
prep.execute();
break;
case 2:
prep.executeUpdate();
break;
case 3:
stat.executeQuery("select 1");
break;
case 4:
stat.execute("select 1");
break;
case 5:
stat.execute("delete from test");
break;
}
}
} catch (SQLException e) {
ex[0] = e;
}
}
};
t.start();
Thread.sleep(100);
conn.close();
t.join();
SQLException e = ex[0];
if (e != null && ErrorCode.OBJECT_CLOSED != e.getErrorCode()) {
throw e;
}
}
}
}
Markdown 格式
0%
您添加了 0 到此讨论。请谨慎行事。
请先完成此评论的编辑!
注册 或者 后发表评论